[GH-ISSUE #5459] OAuth 2.1 Compliance for MCP Plugin #18884

Closed
opened 2026-04-15 17:34:19 -05:00 by GiteaMirror · 4 comments
Owner

Originally created by @jonathanpalma on GitHub (Oct 21, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/5459

Is this suited for github?

  • Yes, this is suited for github

The MCP plugin currently implements OAuth 2.0, but OAuth 2.1 is consolidating best security practices that have emerged over the past decade. While the MCP plugin already implements many OAuth 2.1 features (PKCE support, authorization code flow, public client distinction), it's not fully compliant with the OAuth 2.1 specification by default.

This creates potential security concerns:

  • PKCE is optional rather than mandatory, leaving authorization code flows vulnerable to interception attacks
  • The "plain" code challenge method is allowed by default, which is weaker than S256
  • Refresh tokens for public clients aren't sender-constrained or one-time use, allowing token theft/replay attacks
  • The metadata doesn't advertise OAuth 2.1 compliance, making it unclear to clients what security features are
    required

Describe the solution you'd like

Update the MCP plugin to be fully OAuth 2.1 compliant by default while maintaining backward compatibility for existing implementations. The solution would involve:

Phase 1: Mandatory PKCE with S256 (Breaking Change)

  • Make requirePKCE: true by default
  • Make allowPlainCodeChallengeMethod: false by default (only allow S256)
  • Add clear migration documentation for existing clients

Phase 2: Refresh Token Rotation for Public Clients

  • Implement one-time use refresh tokens for public clients
  • Invalidate old refresh token when a new one is issued
  • Keep current behavior for confidential clients

Phase 3: Enhanced Metadata

  • Update discovery metadata to advertise OAuth 2.1 compliance
  • Document exact redirect URI matching behavior
  • Add OAuth 2.1 specific metadata fields (authorization_response_iss_parameter_supported, etc.)

Phase 4: Testing & Documentation

  • Comprehensive test coverage for OAuth 2.1 requirements
  • Migration guide for existing implementations
  • Documentation on OAuth 2.1 compliance features

Describe alternatives you've considered

  1. Opt-in OAuth 2.1 mode - Add oauth21Compliant: true flag to maintain full backward compatibility initially
mcp({
    loginPage: "/login",
    oauth21Compliant: true, // Enforces all OAuth 2.1 requirements
})
  1. Deprecation warnings - Keep current defaults but warn users about upcoming OAuth 2.1 enforcement
  2. Separate plugin - Create a new mcp21() plugin alongside existing mcp() (less desirable due to code duplication)

Additional context

Current Compliance Status

Already compliant:

  • Authorization code flow only (no implicit grant)
  • Public vs confidential client distinction
  • Bearer tokens via header (not query string)
  • Exact redirect URI matching

⚠️ Gaps to address:

  • PKCE not mandatory by default (requirePKCE option exists but needs to default to true)
  • Plain code challenge method allowed (should only allow S256 unless technically impossible)
  • No refresh token rotation for public clients

Implementation Locations

Key files to modify:

  • /packages/better-auth/src/plugins/mcp/index.ts - Default options and token endpoint
  • /packages/better-auth/src/plugins/mcp/authorize.ts - PKCE enforcement
  • /packages/better-auth/src/plugins/mcp/mcp.test.ts - Test coverage

Backward Compatibility Considerations

Since Better Auth prioritizes stability (per CONTRIBUTING.md), I propose:

  1. Implement OAuth 2.1 mode as opt-in initially (v1.x)
  2. Add deprecation warnings for non-compliant configurations
  3. Make OAuth 2.1 the default in next major version (v2.0)

This allows existing implementations time to migrate while new implementations get secure defaults.

References

Offer to Contribute

I'm happy to contribute this implementation! I can:

  • Create focused PRs for each phase
  • Write comprehensive tests following existing patterns
  • Document migration paths for existing users
  • Work with maintainers on backward compatibility strategy

Please let me know if this approach aligns with Better Auth's roadmap and I'll start with Phase 1 (or whichever phase you'd prefer to prioritize).

Originally created by @jonathanpalma on GitHub (Oct 21, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/5459 ### Is this suited for github? - [x] Yes, this is suited for github ### Is your feature request related to a problem? Please describe. The MCP plugin currently implements OAuth 2.0, but OAuth 2.1 is consolidating best security practices that have emerged over the past decade. While the MCP plugin already implements many OAuth 2.1 features (PKCE support, authorization code flow, public client distinction), it's not fully compliant with the OAuth 2.1 specification by default. This creates potential security concerns: - PKCE is optional rather than mandatory, leaving authorization code flows vulnerable to interception attacks - The "plain" code challenge method is allowed by default, which is weaker than S256 - Refresh tokens for public clients aren't sender-constrained or one-time use, allowing token theft/replay attacks - The metadata doesn't advertise OAuth 2.1 compliance, making it unclear to clients what security features are required ### Describe the solution you'd like Update the MCP plugin to be fully OAuth 2.1 compliant by default while maintaining backward compatibility for existing implementations. The solution would involve: ### Phase 1: Mandatory PKCE with S256 (Breaking Change) - Make `requirePKCE: true` by default - Make `allowPlainCodeChallengeMethod: false` by default (only allow S256) - Add clear migration documentation for existing clients ### Phase 2: Refresh Token Rotation for Public Clients - Implement one-time use refresh tokens for public clients - Invalidate old refresh token when a new one is issued - Keep current behavior for confidential clients ### Phase 3: Enhanced Metadata - Update discovery metadata to advertise OAuth 2.1 compliance - Document exact redirect URI matching behavior - Add OAuth 2.1 specific metadata fields (`authorization_response_iss_parameter_supported`, etc.) ### Phase 4: Testing & Documentation - Comprehensive test coverage for OAuth 2.1 requirements - Migration guide for existing implementations - Documentation on OAuth 2.1 compliance features ### Describe alternatives you've considered 1. **Opt-in OAuth 2.1 mode** - Add `oauth21Compliant: true` flag to maintain full backward compatibility initially ```typescript mcp({ loginPage: "/login", oauth21Compliant: true, // Enforces all OAuth 2.1 requirements }) ``` 2. Deprecation warnings - Keep current defaults but warn users about upcoming OAuth 2.1 enforcement 3. Separate plugin - Create a new `mcp21()` plugin alongside existing `mcp()` (less desirable due to code duplication) ### Additional context ### Current Compliance Status #### ✅ Already compliant: - Authorization code flow only (no implicit grant) - Public vs confidential client distinction - Bearer tokens via header (not query string) - Exact redirect URI matching #### ⚠️ Gaps to address: - PKCE not mandatory by default (requirePKCE option exists but needs to default to true) - Plain code challenge method allowed (should only allow S256 unless technically impossible) - No refresh token rotation for public clients ### Implementation Locations #### Key files to modify: - `/packages/better-auth/src/plugins/mcp/index.ts` - Default options and token endpoint - `/packages/better-auth/src/plugins/mcp/authorize.ts` - PKCE enforcement - `/packages/better-auth/src/plugins/mcp/mcp.test.ts` - Test coverage ### Backward Compatibility Considerations Since Better Auth prioritizes stability (per `CONTRIBUTING.md`), I propose: 1. Implement OAuth 2.1 mode as opt-in initially (v1.x) 2. Add deprecation warnings for non-compliant configurations 3. Make OAuth 2.1 the default in next major version (v2.0) This allows existing implementations time to migrate while new implementations get secure defaults. ### References - https://datatracker.ietf.org/doc/draft-ietf-oauth-v2-1/ - https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics - Current MCP implementation already follows many best practices ## Offer to Contribute I'm happy to contribute this implementation! I can: - Create focused PRs for each phase - Write comprehensive tests following existing patterns - Document migration paths for existing users - Work with maintainers on backward compatibility strategy Please let me know if this approach aligns with Better Auth's roadmap and I'll start with Phase 1 (or whichever phase you'd prefer to prioritize).
GiteaMirror added the lockedenhancement labels 2026-04-15 17:34:19 -05:00
Author
Owner

@dvanmali commented on GitHub (Oct 21, 2025):

@jonathanpalma feel free to try out #4163 👍 it is currently being extensively tested but let me know if you have any issues. You may download using the pkg.pr.new located in the CI to test.

<!-- gh-comment-id:3429922926 --> @dvanmali commented on GitHub (Oct 21, 2025): @jonathanpalma feel free to try out #4163 👍 it is currently being extensively tested but let me know if you have any issues. You may download using the pkg.pr.new located in the CI to test.
Author
Owner

@dvanmali commented on GitHub (Dec 24, 2025):

Hi all, we released the new OAuth Provider Plugin. Feel free to let us know how it works :)

<!-- gh-comment-id:3688535430 --> @dvanmali commented on GitHub (Dec 24, 2025): Hi all, we released the new [OAuth Provider Plugin](https://www.better-auth.com/docs/plugins/oauth-provider). Feel free to let us know how it works :)
Author
Owner

@Muzammillcoste commented on GitHub (Jan 20, 2026):

Has anyone here implemented OAuth 2.1 for an MCP server?

I’m currently working on implementing it, but I’m running into a few issues. I’m following the official documentation, but it feels incomplete and not very clear, and I haven’t been able to finish the implementation successfully.
Has anyone here done this before or can help guide me through it?

<!-- gh-comment-id:3774279790 --> @Muzammillcoste commented on GitHub (Jan 20, 2026): **Has anyone here implemented OAuth 2.1 for an MCP server?** I’m currently working on implementing it, but I’m running into a few issues. I’m following the official documentation, but it feels incomplete and not very clear, and I haven’t been able to finish the implementation successfully. Has anyone here done this before or can help guide me through it?
Author
Owner

@dvanmali commented on GitHub (Jan 20, 2026):

@Muzammillcoste There's a section on MCP authentication

<!-- gh-comment-id:3774841937 --> @dvanmali commented on GitHub (Jan 20, 2026): @Muzammillcoste There's a section on [MCP authentication](https://www.better-auth.com/docs/plugins/oauth-provider#mcp)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#18884