MCP auth — requiring a consent dialog before MCP server sends end user through 3rd party auth #265
Replies: 3 comments 1 reply
-
|
@irvinebroque do you want to propose a chance to #284 where we can make sure that we properly include it in the spec? There are a few pieces in the RFC that allude to it, but maybe we can discuss it with the crew that is currently reviewing the proposal. |
Beta Was this translation helpful? Give feedback.
-
|
@irvinebroque 👋 I've taken a stab at writing this up as a security consideration here, lmkwyt |
Beta Was this translation helpful? Give feedback.
-
|
Something like this? this is Tool Authorization. The end user needs to approve the usage of the servers access and actions taken by the server tools on their behalf of the agent (using the server tools). New Auth just merged to MCP just more like Auth to the server, not what the server does. However, with the unique identifier provided by this, it's possible to implemenet user approval systems, oauth token retrieval/storage/refresh/etc, in the MCP server code. those who don't want to deal with auth, building, or serving tools can also use services like Arcade.dev (demo with claude shown above) |
Beta Was this translation helpful? Give feedback.

Uh oh!
There was an error while loading. Please reload this page.
-
Pre-submission Checklist
Discussion Topic
Context
As described in the MCP spec, when there is a 3rd party auth provider, there are four actors:
MCP clients obtain client IDs without user interaction — dynamic client registration (link). Most OAuth providers (ex: GitHub) do not support dynamic client registration. This means that for a given end user, there exists a many-to-one relationship between MCP clients and a single upstream authorization grant. An end user who logs into Claude on desktop, and then on mobile, has multiple MCP client sessions, sharing a single authorization with the upstream OAuth provider.
Problem
As described here, consider the following example (link), where GitHub is the upstream OAuth provider to the MCP server.
A bad actor can:
https://mymcp.example/authorize?client_id=<ID>&redirect_uri=https://evil.exampleSo long as the bad actor can convince the end user to click the URL, this allows the bad actor access to the token that the MCP server issued, allowing it to call MCP tools, etc. (but not direct access to the upstream provider).
The core problem is that there is no opportunity for the end user to consent to grant access. In this example, they are sent to the GitHub authorization URL (link), but because the end user has already authorized the MCP server (remember that the MCP server here is acting as the OAuth client) — GitHub does not present a consent dialog to the end user. We believe strongly that GitHub and other OAuth providers should present a consent dialog every time that an end user is sent through authorization, but many today do not.
What should end users see?
Ideally the end user would first be presented with a consent dialog:
Then, only once the end user consents, they would be sent to the authorization flow of the upstream OAuth provider (GitHub).
This is necessary because — even if the 3rd party OAuth provider (GitHub) did always show a consent dialog, it would today show something like:
…because it is the MCP server that is the OAuth client. Because the MCP client isn’t directly requesting access, the consent page can’t clearly show the identity of the MCP client that will ultimately gain access to make requests to the MCP server. The end user has no way of seeing this, it’s not clear to them what client they are granting access to, in the case of a link from a bad actor.
And because most OAuth providers do not themselves support dynamic client registration, there is no way for the MCP server to dynamically create a new OAuth client ID with GitHub, and maintain a 1:1 mapping between MCP Client ID and an OAuth client ID used with the upstream provider (GitHub).
This consent dialog would allow the MCP server to explain why they are sending the end user through a 3rd party authorization.
How could the MCP spec be improved to solve this?
It seems like there are two paths:
(1) is the ideal end state. But much more challenging as it requires existing OAuth providers to change in ways that they may not be willing or able to, at least easily. (2) is more friction for end users, and more complexity for MCP servers to get right.
Functionally, (2) would mean the MCP server must do something like store a cookie during the initial consent screen and tie the state value sent upstream to that cookie, so when redirected back, the MCP server can (and must) verify that the user actually did see and consent.
(2) effectively makes MCP auth look like this to the end user:
This maps most literally to what is happening, it is the most clearly explicit. But it means that every MCP server must implement and render some dialog for (1). It’s not clear that there can be a safe and trusted way for (1) to be rendered more directly by the MCP client, since the MCP client is untrusted.
Assuming Option 2 — what would MCP server implementation do?
When the MCP client sends the end user to the /authorize endpoint, the MCP server will need to:
MCP servers probably need helpers for a default consent dialog page that developers can simply plug in and use — and then can modify as-needed. Ex: a helper that redirects to the consent URL, and a helper that renders a page with the consent dialog. And somewhere within these, a cookie gets set automatically. Point is — there's a bit more here for MCP servers and tooling around them to handle on behalf of developers, in order to make this truly easy and pluggable.
What should OAuth providers support, in order to make this simpler?
As noted above, OAuth providers should:
It seems like the MCP spec could make this explicit, even if it does not make it mandatory?
Beta Was this translation helpful? Give feedback.
All reactions