feat(auth): add unified auth protocol discovery and optional DPoP support#2003
Open
nypdmax wants to merge 60 commits intomodelcontextprotocol:mainfrom
Open
feat(auth): add unified auth protocol discovery and optional DPoP support#2003nypdmax wants to merge 60 commits intomodelcontextprotocol:mainfrom
nypdmax wants to merge 60 commits intomodelcontextprotocol:mainfrom
Conversation
…, WWW-Authenticate extensions
…iProtocolAuthProvider
…protocol, protocol_preferences
…vers_discovery_routes
…ig for examples/clients - Add examples/clients/simple-auth-multiprotocol-client (API Key + mTLS placeholder) - Pyright: include examples/clients; executionEnvironments + extraPaths for client packages - Fixes import resolution for mcp_simple_auth_multiprotocol_client.main in __main__.py
…rotocol integration test script - APIKeyVerifier: optional scopes param for AccessToken (satisfy required_scopes) - simple-auth-multiprotocol: build_multiprotocol_backend(api_key_scopes=[mcp_scope]) - scripts/run_phase2_multiprotocol_integration_test.sh: api_key (default), oauth (AS+RS+simple-auth-client), mutual_tls (placeholder)
…lign resource_metadata_url with 401 branch
…d optional http_client to discover_metadata
…erator and storage - Add DPoPKeyPair for ES256/RS256 key generation with configurable RSA key size - Add DPoPProofGeneratorImpl for generating DPoP proof JWTs per RFC 9449 - Add InMemoryDPoPStorage for key pair persistence - Add compute_jwk_thumbprint for RFC 7638 JWK Thumbprint calculation - Include comprehensive unit tests (12 test cases)
Add DPoPProofVerifier for validating DPoP proof JWTs per RFC 9449 Section 4.3, including replay protection, claim validation, and JWK thumbprint verification.
Add DPoP support to OAuth2Protocol implementing DPoPEnabledProtocol, inject DPoP proofs via MultiProtocolAuthProvider, and verify DPoP-bound tokens in OAuthTokenVerifier.
Add --dpop-enabled CLI flag and integrate DPoPProofVerifier with MultiProtocolAuthBackend for end-to-end DPoP verification.
- Add scripts/run_phase4_dpop_integration_test.sh for automated DPoP tests - Update test_oauth2_protocol: expect OAuthFlowError when http_client is None - Update simple-auth-multiprotocol-client: OAuth+DPoP support, InMemoryStorage - Update simple-auth-multiprotocol: DPoP logging, oauth2 protocol_version 2.0
- Add _oauth_401_flow.py: oauth_401_flow_generator, oauth_403_flow_generator - Refactor OAuthClientProvider.async_auth_flow to drive shared generators - Refactor MultiProtocolAuthProvider 401 handling to use shared OAuth flow - Fix OAuth2Protocol.authenticate to use fresh client when called outside flow - Fix OAuthTokenVerifier: use scope for HTTP method (HTTPConnection compat)
Prefer only locally injected protocol instances when selecting the auth protocol, and ensure the final response corresponds to the original request (avoid leaking discovery responses).
Add regression tests ensuring 401 handling falls back when the server default protocol isn't injected, and that discovery responses are never returned as the business request response.
Make api_key and mutual_tls runs non-interactive with clear PASS/FAIL, add oauth_dpop mode wiring, and allow forcing mutual_tls protocol injection for placeholder coverage.
…eAdapter and unit tests
Ignore /plans/ and /.cursorrules to keep local scratch docs and Cursor config out of version control.
- OAuthClientProvider: add fixed_client_info, _exchange_token_client_credentials - OAuth2Protocol: accept fixed_client_info for M2M flows - MultiProtocolAuthProvider: pass fixed_client_info into OAuthClientProvider - _oauth_401_flow: require client_info for client_credentials, skip dynamic registration - Server token handler: ClientCredentialsRequest, exchange_client_credentials - Server routes: advertise client_credentials in grant_types_supported
…overy variants - simple-auth: exchange_client_credentials, demo client_credentials client - simple-auth-multiprotocol: add prm_only, path_only, root_only, oauth_fallback server variants and CLI entry points for discovery E2E testing
Also sync grant_types_supported test assertions with 6cf977b.
- authorization-multiprotocol.md: discovery order (PRM → path-relative → root → OAuth fallback), client flow, [Auth discovery] DEBUG logs - auth-analysis.md: multi-protocol discovery order and logging in §4.2, §12.1.3, §13.2.2 - multi-protocol-refactoring-plan.md: §11.4 PRM-first order, §11.5 note, §3.2.2 pseudo-code; auth discovery logging
Update multiprotocol docs/READMEs to use MCP_AUTH_PROTOCOL (no PHASE wording) and align example instructions with the hardened scripts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation and Context
This PR adds multi-protocol authentication support to the MCP Python SDK, centered around unified authorization
server discovery so clients can discover, select, and apply one of multiple supported auth protocols consistently.
Key capabilities:
/.well-known/authorization_serversplus RFC 9728 PRM fallback.oauth2,api_key) with optional default protocol andpreferences.
FastMCPcompatibility wrapper used by examples and updates multiprotocol examples.How Has This Been Tested?
PYTEST_DISABLE_PLUGIN_AUTOLOAD="" uv run --frozen pytestuv run --frozen ruff format --check .uv run --frozen ruff check .uv run --frozen pyrightSpec compliance notes (additive extensions)
This PR keeps MCP Authorization (2025-06-18) OAuth behavior intact (RFC 9728 PRM + RFC 8414 metadata + RFC 8707
resource indicators). It also adds optional extensions to support multi-protocol auth and stronger token binding:
Multi-protocol selection (extension):
/.well-known/authorization_serversendpoint (best-effort; client falls back if missing).mcp_auth_protocols,mcp_default_auth_protocol,mcp_auth_protocol_preferences.WWW-Authenticate: Bearer ...hint params:auth_protocols,default_protocol,protocol_preferences(ignored by spec-only clients).
DPoP (RFC 9449) (optional extension): adds opt-in DPoP proof generation/verification; standard Bearer flow remains
supported when disabled.
Interoperability: spec-only servers/clients can ignore these extensions and continue using the standard OAuth discovery
and Bearer token flow.
Breaking Changes
None expected. Changes are additive and aim to preserve existing behavior and public APIs.
Types of changes
Checklist
Additional context
Suggested review order (commit-by-commit):
FastMCPwrapper + updated examples