feat(python): MCP server OAuth form quick wins (read-only redirect URI, drop password grant) - #6315
Merged
Merged
Conversation
…rver-side Scoped to the backend-only pieces of #5721: GatewayCreate rejects the OAuth 2.1 resource owner password grant for new MCP server registrations (GatewayUpdate still accepts it for existing records), and initiate_oauth_flow/oauth_callback default a missing redirect_uri to {app_domain}/oauth/callback so authorization_code configs created via the API or predating this change don't hit OAuthManager's PKCE paths without one. Signed-off-by: Marek Dano <mk.dano@gmail.com>
…ix root_path default - GatewayUpdate now rejects newly adopting the deprecated password grant on a gateway that wasn't already using it, closing the path that let the GatewayCreate-time rejection be bypassed via update. - redirect_uri defaulting now accounts for app_root_path and logs when applied; the fallback is centralized in OAuthManager instead of duplicated across both /oauth router endpoints, so any future caller is protected too. - redirect_uri is pinned into OAuth state at authorize time and reused at token exchange, so it can't diverge between the two legs if gateway config or app_domain changes mid-flow (RFC 6749 §4.1.3). - Removes the deprecated password grant option from the legacy admin gateway-creation form (edit form still allows it, for existing configs). - Adds redirect_uri column to oauth_states (migration included). Signed-off-by: Marek Dano <Marek.Dano@ibm.com>
msureshkumar88
requested review from
Lang-Akshay,
brian-hussey,
crivetimihai and
ja8zyjits
as code owners
August 20, 2026 09:49
added 2 commits
August 20, 2026 10:57
db41939315aa branched off e4f5a6b7c8d9, same parent as 9935d863930b_add_metrics_read_to_default_roles.py which landed on main after this branch diverged, producing two Alembic heads and breaking DB bootstrap in CI (SQLite/PostgreSQL fresh/upgrade, playwright smoke, pre-commit alembic-check-heads). Signed-off-by: Suresh Kumar Moharajan <suresh12.dmm@gmail.com> Signed-off-by: Suresh Kumar Moharajan <suresh.kumar.m@ibm.com>
Signed-off-by: Suresh Kumar Moharajan <suresh12.dmm@gmail.com> Signed-off-by: Suresh Kumar Moharajan <suresh.kumar.m@ibm.com>
Closed
14 tasks
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.
Pull Request
🔗 Related Issue
Relates to #5721 (delivers the backend pieces of User Stories 1, 2, and 4; Story 3 — pre-fill from MCP
initialize— is deferred, see #5719).Supersedes #5786 — same commits, rebased onto current
main. That PR's head branch lives on a fork we don't have push access to, so a fresh PR against a branch on this repo was needed to land the already-reviewed and approved rebase.📝 Summary
Backend half of the MCP server OAuth form quick wins: closes an OAuth 2.1 foot-gun (deprecated password grant) and hardens
redirect_urihandling for the authorization-code flow. The React UI half now lives in contextforge-org/contextforge-web-ui#15.GatewayCreaterejectsgrant_type == "password"at the schema layer, so new MCP server registrations can't use it regardless of how they're created (UI or API). Existing gateways that already use it keep working throughGatewayUpdate— butGatewayUpdatenow also rejects newly adopting password on a gateway that wasn't already using it, so the create-time restriction can't be bypassed via the update path. The legacy admin UI's gateway creation form no longer offers the option either (the edit form still does, for loading/saving existing legacy configs).redirect_uridefaulting (Story 1, server-side):initiate_oauth_flowandoauth_callbackdefault a missingredirect_urito the gateway's own global callback ({app_domain}{app_root_path}/oauth/callback), so API-created and legacy configs can't reachOAuthManager's PKCE paths without one. The default accounts for a reverse-proxyapp_root_path, logs when it's actually applied, and the substitution logic is centralized inOAuthManager.redirect_uripinned across the flow: the value sent to the IdP at authorize time is now pinned into server-side OAuth state (alongside the PKCEcode_verifier) and reused at token-exchange time, so a concurrent gateway config change orapp_domainchange between authorize and callback can't cause the two to diverge (RFC 6749 §4.1.3). Adds aredirect_uricolumn tooauth_states(migration included).All review feedback from #5786 (password-grant update loophole,
app_root_pathhandling, missing logging, redirect_uri pinning, legacy UI option) is already addressed in these commits, and the PR was approved there before the rebase.📏 Reviewability
triage🏷️ Type of Change
🧪 Verification
pytest tests/unit/mcpgateway/test_schemas_validators_extra.py tests/unit/mcpgateway/services/test_gateway_service.py -k "oauth or gateway_create or gateway_update or password"pytest tests/unit/mcpgateway/routers/test_oauth_router.pypytest tests/unit/mcpgateway/services/test_oauth_manager.pyalembic heads✅ Checklist