fix(OAuth): honor token_endpoint_auth_method in OAuth token exchange#4717
Open
Conversation
Fixes #4706 When DCR registers a client with token_endpoint_auth_method set to 'client_secret_basic' (RFC 7591 default), the token exchange now correctly uses HTTP Basic Authentication instead of always sending credentials in the POST body. Changes: - oauth_manager.py: Updated exchange_code_for_token() to read and honor token_endpoint_auth_method from credentials - oauth_router.py: Propagate token_endpoint_auth_method from DCR registered client to oauth_config - Added test coverage for Basic Auth fallback when client_secret missing - Updated DCR tests to include token_endpoint_auth_method attribute This ensures compatibility with strict OAuth 2.1 providers like Datadog that enforce the registered authentication method. Signed-off-by: Bogdan-Marius-Catanus <bogdan-marius.catanus@ibm.com>
added 2 commits
May 12, 2026 13:06
Signed-off-by: Bogdan-Marius-Catanus <bogdan-marius.catanus@ibm.com>
Signed-off-by: Bogdan-Marius-Catanus <bogdan-marius.catanus@ibm.com>
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.
🔗 Related Issue
Closes #4706
📝 Summary
This PR fixes a critical OAuth 2.1 compatibility issue where ContextForge ignored the
token_endpoint_auth_methodsetting during authorization code token exchange, causing failures with strict OAuth providers like Datadog.Problem: When DCR registers a client and the authorization server defaults to
token_endpoint_auth_method: "client_secret_basic"(RFC 7591 §2 default), the subsequent token exchange always sent credentials in the POST body (client_secret_post), resulting in400 invalid_clienterrors from strict OAuth 2.1 providers.Solution:
exchange_code_for_token()to read and honortoken_endpoint_auth_methodfrom credentialstoken_endpoint_auth_methodfrom DCR-registered clients to the OAuth configclient_secret_basicis specifiedImpact: Enables ContextForge to work with strict OAuth 2.1 providers (Datadog, and others) that enforce the registered authentication method.
🏷️ Type of Change
🧪 Verification
make lintmake testmake coverage✅ Checklist
make black isort pre-commit)📓 Notes
Technical Details
Files Modified:
mcpgateway/services/oauth_manager.py(lines 639-665)token_endpoint_auth_methoddetection from runtime credentialsmcpgateway/routers/oauth_router.py(line 447)token_endpoint_auth_methodfrom DCRregistered_clienttooauth_configTest Updates:
token_endpoint_auth_methodattributeAlready Working Correctly
_exchange_code_for_tokens()(PKCE path) - already honored the settingrefresh_token()- already honored the settingWhy Other Providers Didn't Fail
Auth0, Okta, Google, Microsoft are lenient per RFC 6749 §2.3.1 and accept either authentication method. Datadog and other strict OAuth 2.1 servers enforce the registered method, exposing this bug.
Testing Against Datadog
To verify the fix works with Datadog MCP server:
issuer: "https://mcp.datadoghq.com"client_secret_basic400 invalid_client)