Skip to content

feat: implement RFC 6750 Bearer token authentication #18644

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint
Choose a base branch
from

Conversation

ThomasK33
Copy link
Member

Add RFC 6750 Bearer Token Authentication Support

This PR implements RFC 6750 Bearer Token authentication as an additional authentication method for Coder's API. This allows clients to authenticate using standard OAuth 2.0 Bearer tokens in two ways:

  1. Using the Authorization: Bearer <token> header
  2. Using the access_token query parameter

Key changes:

  • Added support for extracting tokens from both Bearer headers and access_token query parameters
  • Implemented proper WWW-Authenticate headers for 401/403 responses with appropriate error descriptions
  • Added comprehensive test coverage for the new authentication methods
  • Updated the OAuth2 protected resource metadata endpoint to advertise Bearer token support
  • Enhanced the OAuth2 testing script to verify Bearer token functionality

These authentication methods are added as fallback options, maintaining backward compatibility with Coder's existing authentication mechanisms. The existing authentication methods (cookies, session token header, etc.) still take precedence.

This implementation follows the OAuth 2.0 Bearer Token specification (RFC 6750) and improves interoperability with standard OAuth 2.0 clients.

@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch from ff83df4 to 3665807 Compare June 27, 2025 17:02
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint branch from 5898895 to 5be6c6a Compare June 27, 2025 17:02
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch from 3665807 to 56126dd Compare June 27, 2025 17:11
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint branch from 5be6c6a to fded148 Compare June 27, 2025 17:29
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch 2 times, most recently from fca6b9a to 68baa21 Compare June 27, 2025 17:54
@ThomasK33 ThomasK33 marked this pull request as ready for review June 29, 2025 11:14
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch from 68baa21 to 578e708 Compare June 30, 2025 11:06
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint branch 2 times, most recently from 9b7f5d9 to 7ef25b1 Compare June 30, 2025 11:49
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch from 578e708 to 26c0eeb Compare June 30, 2025 11:49
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint branch from 7ef25b1 to f0608bc Compare June 30, 2025 12:02
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch from 26c0eeb to 7b70f7f Compare June 30, 2025 12:02
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint branch from f0608bc to c68a923 Compare June 30, 2025 12:31
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch from 7b70f7f to 1a9400e Compare June 30, 2025 12:31
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint branch from c68a923 to f55771a Compare June 30, 2025 12:46
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch 2 times, most recently from 5f946b1 to 14d91ac Compare June 30, 2025 12:53
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint branch from f55771a to 34af681 Compare June 30, 2025 12:53
@ThomasK33 ThomasK33 requested review from Emyrk and johnstcn June 30, 2025 13:21
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch from 0f4491b to 8c975b5 Compare June 30, 2025 16:45
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint branch from 1a99f3c to 01a10ef Compare June 30, 2025 17:56
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch from 8c975b5 to 017f23f Compare June 30, 2025 17:56
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the significance of extended versus the regular test?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea was that rfc6750_test.go contain basic RFC 6750 compliance tests (authentication methods, basic token validation), while the rfc6750_extended_test.go contain security and edge case testing (malformed headers, precedence, WWW-Authenticate compliance, etc.).

@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch from 017f23f to 77e3e55 Compare July 1, 2025 09:15
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint branch from 01a10ef to 3b6d8ba Compare July 1, 2025 09:27
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch from 77e3e55 to 1e1e046 Compare July 1, 2025 09:27
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint branch from 3b6d8ba to dac326d Compare July 1, 2025 13:23
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch from 1e1e046 to 17982a7 Compare July 1, 2025 13:23
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint branch from dac326d to 1858134 Compare July 1, 2025 13:41
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch from 17982a7 to 119626d Compare July 1, 2025 13:41
Copy link
Member

@johnstcn johnstcn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving but would like a second pair of eyes.

Comment on lines +225 to +228
case strings.Contains(response.Message, "expired") || strings.Contains(response.Detail, "expired"):
wwwAuth = `Bearer realm="coder", error="invalid_token", error_description="The access token has expired"`
case strings.Contains(response.Message, "audience") || strings.Contains(response.Message, "mismatch"):
wwwAuth = `Bearer realm="coder", error="invalid_token", error_description="The access token audience does not match this resource"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very unfortunate we have to do string matches 😢

@Emyrk Emyrk requested a review from Copilot July 1, 2025 15:40
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements RFC 6750 Bearer Token authentication as a fallback method, adds corresponding tests, and updates metadata to advertise Bearer support.

  • Added shell tests for header/query parameter authentication and metadata endpoint in test-mcp-oauth2.sh
  • Updated Go metadata endpoint and its tests to include BearerMethodsSupported
  • Extended middleware (apikey.go) to extract Bearer tokens and set proper WWW-Authenticate headers

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
scripts/oauth2/test-mcp-oauth2.sh Add tests for Bearer header, query parameter, and metadata
coderd/oauth2_metadata_test.go Update protected-resource metadata tests to expect Bearer methods
coderd/oauth2.go Enable BearerMethodsSupported in the metadata response
coderd/httpmw/rfc6750_test.go Add unit tests for basic RFC 6750 header/query extraction
coderd/httpmw/rfc6750_extended_test.go Expand security, precedence, and compliance tests for RFC 6750
coderd/httpmw/apikey.go Implement Bearer token extraction and WWW-Authenticate headers
Comments suppressed due to low confidence (2)

scripts/oauth2/test-mcp-oauth2.sh:210

  • The test references RFC 9728 but the OAuth 2.0 protected resource metadata spec is RFC 9126. Update the reference for accuracy.
echo -e "${YELLOW}Test 7: Protected Resource Metadata (RFC 9728)${NC}"

scripts/oauth2/test-mcp-oauth2.sh:200

  • Add a complementary test for 403 Forbidden responses to verify the insufficient_scope WWW-Authenticate header is set correctly.
# Test WWW-Authenticate header on unauthorized request

@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint branch from 1858134 to a239eaa Compare July 1, 2025 16:50
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch 2 times, most recently from 6487981 to b612336 Compare July 1, 2025 16:56
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint branch from a239eaa to 4ca3595 Compare July 1, 2025 16:56
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch 2 times, most recently from dd8ddee to 54580fa Compare July 1, 2025 17:18
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint branch from 4ca3595 to 23374cd Compare July 1, 2025 17:18
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch from 54580fa to 21cdd55 Compare July 1, 2025 19:54
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint branch from 23374cd to 43fcceb Compare July 1, 2025 19:54
- Add RFC 6750 bearer token extraction to APITokenFromRequest as fallback methods
- Support Authorization: Bearer <token> header and access_token query parameter
- Maintain backward compatibility by prioritizing existing custom methods first
- Add WWW-Authenticate headers to 401/403 responses per RFC 6750
- Update Protected Resource Metadata to advertise bearer_methods_supported
- Add comprehensive test suite for RFC 6750 compliance in rfc6750_test.go
- Update MCP test scripts with bearer token authentication tests
- Enhance CLAUDE.md with improved Go LSP tool usage guidelines

Implements RFC 6750 Section 2.1 (Authorization Request Header Field) and 2.3 (URI Query Parameter).
Maintains full backward compatibility with existing Coder authentication methods.
Completes major MCP OAuth2 compliance milestone.

Change-Id: Ic9c9057153b40728ad91b377d753a7ffd566add7
Signed-off-by: Thomas Kosiewski <[email protected]>
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_9728_protected_resource_metadata_endpoint branch from 43fcceb to db5e215 Compare July 1, 2025 20:14
@ThomasK33 ThomasK33 force-pushed the thomask33/06-27-feat_oauth2_implement_rfc_6750_bearer_token_support_for_mcp_compliance branch from 21cdd55 to 2410fd8 Compare July 1, 2025 20:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants