-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Prevent confused deputy attacks in OAuth proxy #2056
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
Conversation
Implements user consent requirement before OAuth authorization completes, protecting against confused deputy attacks per MCP security best practices. When a new or unrecognized MCP client attempts authorization, users see a consent page showing client details, redirect URI, and requested scopes before approving. Key features: - Consent page with client details and scope display - CSRF-protected approval/denial with cryptographically signed cookies - Storage-backed transaction management for server restarts - Responsive UI with security tooltip explaining protection - Auto-approval for previously consented clients Creates shared UI utilities module (src/fastmcp/utilities/ui.py) with reusable HTML/CSS components for OAuth pages, consent flows, and future user-facing interfaces.
@strawgate this is a great test case for the new OAuth storage mechanisms |
# Need to allow form-action for form submission | ||
csp_policy = "default-src 'none'; style-src 'unsafe-inline'; img-src https:; base-uri 'none'; form-action *" | ||
|
||
return create_page( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super excited to see this and with remote storage for all state! Sorry if I am commenting too early but would be great if the consent page could be customizable to show more of the brand of the MCP server, and the very least, be able to replace "FastMCP" with the server name and the logo. Or maybe just be able to pass in an entire custom HTML - Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree! At the moment auth modules don't receive the server (other way around) so I punted on e.g. server name for this draft because it required more changes than I wanted in this PR
Feeling good about the state of this and want to continue iterating on some token storage concerns without polluting it so I'm going to merge this as we continue pressing on state / storage for sensitive items. |
FastMCP's OAuth proxy uses a static client ID when forwarding authorization requests to upstream providers. This creates a confused deputy vulnerability: an attacker can register a malicious client via the open DCR endpoint, then trick a victim into authorizing it. Because the victim already has a consent cookie for the static client ID, the upstream authorization server bypasses the consent screen and issues an authorization code that redirects to the attacker's server.
This PR implements the mitigation required by the MCP specification: the proxy now obtains explicit user consent for each dynamically registered client before forwarding to the upstream authorization server. It also updates relevant documentation.
The consent flow:
/consent
endpointServer-side storage ensures OAuth transactions and authorization codes persist across requests, with full support for custom storage backends via `AsyncKeyValue`.
Thanks to @localden for identifying this vulnerability and providing detailed analysis on this topic in his blog post.