-
Notifications
You must be signed in to change notification settings - Fork 1.1k
SEP-646: Enterprise-Managed Authorization Profile for MCP #646
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
Co-authored-by: Den Delimarsky 🌺 <53200638+localden@users.noreply.github.com>
Co-authored-by: Den Delimarsky 🌺 <53200638+localden@users.noreply.github.com>
Co-authored-by: Den Delimarsky 🌺 <53200638+localden@users.noreply.github.com>
Co-authored-by: Den Delimarsky 🌺 <53200638+localden@users.noreply.github.com>
Co-authored-by: Den Delimarsky 🌺 <53200638+localden@users.noreply.github.com>
Co-authored-by: Den Delimarsky 🌺 <53200638+localden@users.noreply.github.com>
Co-authored-by: Den Delimarsky 🌺 <53200638+localden@users.noreply.github.com>
Co-authored-by: Den Delimarsky 🌺 <53200638+localden@users.noreply.github.com>
Co-authored-by: Den Delimarsky 🌺 <53200638+localden@users.noreply.github.com>
Co-authored-by: Den Delimarsky 🌺 <53200638+localden@users.noreply.github.com>
Co-authored-by: Den Delimarsky 🌺 <53200638+localden@users.noreply.github.com>
Co-authored-by: Den Delimarsky 🌺 <53200638+localden@users.noreply.github.com>
docs/specification/draft/basic/enterprise-managed-authorization.mdx
Outdated
Show resolved
Hide resolved
docs/specification/draft/basic/enterprise-managed-authorization.mdx
Outdated
Show resolved
Hide resolved
| | `audience` | REQUIRED | The Issuer URL of the MCP server's authorization server. | `https://auth.chat.example/` | | ||
| | `resource` | REQUIRED | The RFC9728 Resource Identifier of the MCP server. | `https://mcp.chat.example/` | | ||
| | `scope` | OPTIONAL | The space-separated list of scopes at the MCP Server that are being requested. | `scope1 scope2` | | ||
| | `subject_token` | REQUIRED | The identity assertion (e.g. the OpenID Connect ID Token or SAML assertion) for the target end-user. | (JWT or SAML assertion string) | |
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.
In the OIDC case, it might be better to use the access token here, assuming that the IdP could authorize a special scope for that token, which tells the user that the client is requesting to access MCP servers with it.
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.
for that to work, the initial OIDC SSO flow would have to include something in addition to the standard SSO flow, to tell the IdP about the future intent. We wanted to be able to do this without anything special on the initial SSO, both for OIDC and SAML.
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.
It was expected that the IdP would need an authorization statement (e.g. policy) that grants the client_id the ability to perform cross-domain access to another AS for specific scopes for a specific set of users. Since the token exchange operation is a intent-based request with context by the client and not just another protected resource it didn't make sense to require a scope (you authorize token-exchange grant type for ID-JAG token type). Its the downstream resource+scopes that matter.
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.
Another benefit of using the access token instead of the ID Token here could be that we could use DPoP by treating the MCP Authorization Server as the resource server. By using @aaronpk 's client URI mechanism, this can also provide client attestation. To do this, the MCP Authorization Server obtains the public key from the client metadata rather than from the access token JWT or token introspection.
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.
It was expected that the IdP would need an authorization statement (e.g. policy) that grants the
client_idthe ability to perform cross-domain access to another AS for specific scopes for a specific set of users. Since the token exchange operation is a intent-based request with context by the client and not just another protected resource it didn't make sense to require a scope (you authorize token-exchange grant type for ID-JAG token type). Its the downstream resource+scopes that matter.
I agree that the token exchange intent was not to scope-limit the exchange, but it might be beneficial from both an enterprise policy point of view (does this user need access to MCP servers right now), or from a user consent point of view in the consumer case (be warned this token gives the client access to MCP servers on your behalf).
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.
I would rather do that by having the client request a new scope from the IdP. There's already OpenID scopes used to indicate what claims to include in an ID token and it feels conceptually similar to that.
Yup. That is indeed what I'm suggesting.
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.
Great, we can do that without changing this to an access token input then.
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.
Ah ok. I guess I was suggesting the scope to be set on the access token. I didn't realize it could be set on the ID Token too.
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.
The possible concern could be overloading the conventional OIDC scopes, if the token contains the permissions(scopes) for (MCP server) then its no longer a authentication only flow, might be more clear to call it OAuth2 explicitly. The client can still request for the scopes in the authorization call itself where the user can explicitly provide consent. The scopes can still be embedded in the Access Token as a part of regular code grant flow or use the access token to request for this new JWT with scopes in case the list of scopes could be too long.
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.
while it can certainly be done, setting the scopes/claims in idToken or using it for accessing the resources could be confusing and anti-pattern on how the idToken is used conventionally
…n.mdx Co-authored-by: Hi120ki <12624257+hi120ki@users.noreply.github.com>
|
I don't know what I clicked to request a review from the docs maintainers team. I think GitHub did that automatically when I pulled in the main branch changes into this. |
docs/specification/draft/basic/enterprise-managed-authorization.mdx
Outdated
Show resolved
Hide resolved
|
Thanks for adding this to the spec—really appreciate the detailed work here! Quick question regarding token lifecycle: what happens when the access_token expires? How does the refresh mechanism work in this setup? Specifically:
Would love some clarification on the expected flow here. Thanks again! Sorry if this is already covered somewhere and I am missing something. Thank you. |
|
@sunishsheth2009 - I asked that above and Aaron opened an issue here to discuss: oauth-wg/oauth-identity-assertion-authz-grant#35 TLDR: the first flow you described: refresh the ID token, new ID-JAG, new access token 👍 ID tokens are meant to be verified and used by the client requesting them so you can use the |
| Location: https://acme.idp.example/authorize?response_type=code&scope=openid&client_id=... | ||
| ``` | ||
|
|
||
| The user authenticates with the IdP, and is redirected back to the Client with an authorization code, which it can then exchange for an ID Token. |
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.
To confirm, this client has access to client secret to complete the authorization code flow for all possible scenarios or would there by any exceptions eg. local clients?
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.
This could also work with public clients, that's really just a policy up to the IDP and AS.
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.
so its safe to assume that a server side component would always be required for this flow to orchestrate it securely
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.
The question of client authentication/identity is not really related to this proposal.
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.
Guess I am just trying to wrap my head around the usage of idToken instead of accessToken, one is more tied in pure client scenarios ( no client secret required) only for identity verification purposes. Is there is any literature about the explicit benefit of using the idToken instead of accessToken given the client secret is always required in the flow.
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.
Is there is any literature about the explicit benefit of using the idToken
The goal of using the idToken is to assert to a 3rd party authorization server the user identity that originated from the idp. The user's access_token is less useful because it represents the user's capabilities at the IDP authz server.
But to this point, because MCP scenarios may be public clients, should we provide guidance on public client authentication in this PR, or perhaps recommend confidential clients? Given that client authentication is part of the processing rules for the Resource Authz Server when validating the ID-JAG?
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.
The risk is that an idToken does not tells anything about how it was obtained, who obtained it, where as an access Token makes the caller a first party since they could have only obtained it with client secret that they had. I may be wrong, still in my opinion an idToken is only good for the first party that obtained it from security perspective
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.
is only good for the first party that obtained it from security perspective
Apologies, I might be confused here on your concern. I beleive what this PR propses is that the id_token is only used in a first-party context - that is, the client application registered with the IdP that requested it, as well as the Idp itself. The exchange between the client and the 3rd party server does not contain any id_token.
|
This has been accepted and merged as an auth extension: modelcontextprotocol/ext-auth#4 |
Motivation and Context
This extension is designed to facilitate secure and interoperable authorization of MCP clients within corporate environments, leveraging existing enterprise identity infrastructure.
How Has This Been Tested?
We have an end to end implementation of this here, and have in-progress implementations with some partners.
Breaking Changes
This is designed to augment the existing OAuth profile by providing an alternative when used under an enterprise IdP. MCP clients can opt in to this profile when necessary.
Types of changes
Checklist
Additional context
For more background on this problem, you can refer to my blog post about this here:
Enterprise-Ready MCP
I also presented this at the MCP Dev Summit in May.
A high level overview of the flow is below:
sequenceDiagram participant UA as Browser participant C as MCP Client participant MAS as MCP Authorization Server participant MRS as MCP Resource Server participant IdP as Identity Provider C-->>UA: Redirect to IdP UA->>IdP: Redirect to IdP Note over IdP: User Logs In IdP-->>UA: IdP Authorization Code UA->>C: IdP Authorization Code C->>IdP: Token Request with IdP Authorization Code IdP-->C: ID Token note over C: User is logged<br>in to MCP Client.<br>Client stores ID Token. C->IdP: Exchange ID Token for ID-JAG note over IdP: Evaluate Policy IdP-->C: Responds with ID-JAG C->MAS: Token Request with ID-JAG note over MAS: Validate ID-JAG MAS-->C: MCP Access Token loop C->>MRS: Call MCP API with Access Token MRS-->>C: MCP Response with Data end