-
Notifications
You must be signed in to change notification settings - Fork 705
feat: Add Enterprise Managed Authorization (SEP-990) support #1305
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
base: main
Are you sure you want to change the base?
Changes from all commits
971dd8b
4d8699a
6390f2a
db67570
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -31,6 +31,38 @@ For more information about MCP: | |||||||
| - [Protocol Specification](https://modelcontextprotocol.io/specification/) | ||||||||
| - [GitHub Organization](https://github.com/modelcontextprotocol) | ||||||||
|
|
||||||||
| ## Enterprise Auth / Enterprise Managed Authorization | ||||||||
|
|
||||||||
| The SDK provides Cross-Application Access support for the [Identity Assertion Authorization Grant flow](https://github.com/modelcontextprotocol/ext-auth/blob/main/specification/draft/enterprise-managed-authorization.mdx), | ||||||||
| enabling enterprise SSO scenarios where users authenticate once via their enterprise Identity Provider and | ||||||||
| access MCP servers without per-server authorization prompts. | ||||||||
|
|
||||||||
| The flow consists of two token operations: | ||||||||
| 1. **RFC 8693 Token Exchange** at the IdP: ID Token → JWT Authorization Grant (JAG) | ||||||||
| 2. **RFC 7523 JWT Bearer Grant** at the MCP Server: JAG → Access Token | ||||||||
|
|
||||||||
| ### Using CrossApplicationAccessProvider | ||||||||
|
|
||||||||
| ```csharp | ||||||||
| using ModelContextProtocol.Authentication; | ||||||||
|
|
||||||||
| var provider = new CrossApplicationAccessProvider(new CrossApplicationAccessProviderOptions | ||||||||
| { | ||||||||
| ClientId = "mcp-client-id", | ||||||||
| IdpTokenEndpoint = "https://company.okta.com/oauth2/token", | ||||||||
| IdpClientId = "idp-client-id", | ||||||||
| IdTokenCallback = async (context, ct) => | ||||||||
| { | ||||||||
| // Return the OIDC ID token from your SSO session | ||||||||
| return myIdToken; | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This callback is
Suggested change
|
||||||||
| } | ||||||||
| }); | ||||||||
|
|
||||||||
| var tokens = await provider.GetAccessTokenAsync( | ||||||||
| resourceUrl: new Uri("https://mcp-server.example.com"), | ||||||||
| authorizationServerUrl: new Uri("https://auth.mcp-server.example.com")); | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We experimented with adding some of these OAuth flows in #1178, but we haven't added it yet since it's an Auth Extension rather than a primary part of the spec. See https://github.com/modelcontextprotocol/ext-auth/blob/5c50488e96e242b4d09c2b97ae47fa152d96a836/specification/draft/enterprise-managed-authorization.mdx and https://github.com/modelcontextprotocol/conformance/blob/066b2d70800a8bd6bca82e000007c9877b443e5b/src/scenarios/client/auth/index.ts#L50-L55. I do like that this doesn't pollute the ClientOAuthOptions like #1178 did, but I wonder if this wouldn't be better as a separate package. It looks like you could use these APIs to get the access token for any HttpClient needing to support these OAuth flows. It seems like something with more features like
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the review @halter73 ! Good points - I want to address the packaging question. Why I placed this in ModelContextProtocol.Core:
That said, I'm happy to move this to a separate package (e.g. ModelContextProtocol.Auth.Enterprise) if the team prefers that pattern for auth extensions. The code is self-contained with no dependencies on SDK internals, so it would be a straightforward move. What do you think?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Makes sense. Are APIs that just provide the access token that we can then use to create a new client sufficient? I know for the normal OAuth flows we need a bit deeper integration to support scope step up and token refresh. I suppose scope step up would be hard without an interactive user and a browser, but refresh seems like it could still be useful. I suppose you could always refresh manually and call ResumeSessionAsync with the new access token. What do the other SDKs do for token refresh in this case?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As for the separate package, I don't think that's necessary. My primary concern would be not making
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the great questions, @halter73! On scope step-up:
On token refresh:
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this PR, that is already supported via:
Your suggestion of calling Let me know if you'd like me to add refresh-on-401 integration or any deeper transport hookup in this PR, or if the current |
||||||||
| ``` | ||||||||
|
|
||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought this was in a conceptual doc. This doubles the size of our README. We try to keep this pretty slim. I would move this to somewhere under the If you want to go the extra mile, you could add this flow to ProtectedMcpServer and ProtectedMcpClient. These both run against the TestOAuthServer that you've already updated, so I think you're already most of the way there. It could be helpful for referencing from the |
||||||||
| ## License | ||||||||
|
|
||||||||
| This project is licensed under the [Apache License 2.0](LICENSE). | ||||||||
Uh oh!
There was an error while loading. Please reload this 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.
I think we should de-emphasize "Enterprise" now that it's no longer part of the type names. This appears to align better with the TS SDK's conceptual docs.
https://github.com/modelcontextprotocol/typescript-sdk/blob/48251fe2cb24fb9b2a12ef3cffb5f5bd196a7ea4/docs/client.md#L169