Skip to content

Feat: Separate authorization server and resource server on client auth flow #416

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

Merged
merged 28 commits into from
May 21, 2025

Conversation

0Itsuki0
Copy link
Contributor

@0Itsuki0 0Itsuki0 commented Apr 27, 2025

Conform to the new authentication protocol by separating authorization server and resource server.

  • add function to discover protected resource metadata
  • use the discovered authorization server url for the auth flow

Motivation and Context

Ensure the sdk functionality conforms to the protocol specification.

How Has This Been Tested?

npm test

  • Modifying Existing tests to make sure they all past
  • Add couple new tests for the authorization-related functions

Breaking Changes

Yes.

  1. The functions arguments in auth.ts other than the auth() function requires authorization server url instead of resource server url.
  2. The flow requires the server to implement OAuth 2.0 Protected Resource Metadata as specified in the authorization section of the protocol.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

None.

@0Itsuki0 0Itsuki0 marked this pull request as ready for review April 27, 2025 10:25
@0Itsuki0 0Itsuki0 changed the title Separate authorization server and resource server on client auth flow Feat: Separate authorization server and resource server on client auth flow Apr 28, 2025
@QuantGeekDev
Copy link

Looking quite good. Thanks for the blog post on this. I'm going to test this out

@QuantGeekDev
Copy link

Code also looks good

@0Itsuki0
Copy link
Contributor Author

0Itsuki0 commented May 7, 2025

Code also looks good

Thank you!

The spec seems to be still under construction, especially the toke validation parts. I am willing to add more if necessary but probably at a different branch would be better?

@QuantGeekDev
Copy link

@0Itsuki0 I built a mcp server with the latest draft of the spec - maybe we can try the client against this? I've been testing with my postman collection so far

@0Itsuki0
Copy link
Contributor Author

@0Itsuki0 I built a mcp server with the latest draft of the spec - maybe we can try the client against this? I've been testing with my postman collection so far

thank you for the server!

I will be happy to try it out and let you know how it goes!

@QuantGeekDev
Copy link

@0Itsuki0 Let me know if I can help with anything. I'm taking a look at the server aspect of the new auth spec

@0Itsuki0
Copy link
Contributor Author

@QuantGeekDev
Hey, I am currently testing out with the MCP server you have shared. I am getting an invalid_request Missing authorization header error while fetching the /.well-known/oauth-protected-resource endpoint. I don't think this endpoint should requires any authorization...
Am I missing anything?

Copy link
Contributor

@pcarleton pcarleton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for sending this! Apologies for the slow response.

I added a few comments. The most substantial was around including resource in the authorization url, which isn't in the spec (but might have been in an earlier draft).

other things were:

  • some extra log lines
  • RFC number fix
  • an import path

It looks like it also needs some merge conflict resolution.

I'm attempting to test this with the server supporting the new spec I've implemented in: #503 , but it will require an example client impl. I'll see about stacking a PR with the example on it

0Itsuki0 and others added 9 commits May 20, 2025 14:51
Co-authored-by: Paul Carleton <[email protected]>
Co-authored-by: Paul Carleton <[email protected]>
Co-authored-by: Paul Carleton <[email protected]>
Co-authored-by: Paul Carleton <[email protected]>
Co-authored-by: Paul Carleton <[email protected]>
Co-authored-by: Paul Carleton <[email protected]>
Co-authored-by: Paul Carleton <[email protected]>
Co-authored-by: Paul Carleton <[email protected]>
@0Itsuki0 0Itsuki0 requested a review from pcarleton May 20, 2025 06:04
@0Itsuki0
Copy link
Contributor Author

@pcarleton
Thank you for the suggestions!
I have committed those changes as well as resolved the conflict!
Please take a look when you get some time.

Copy link
Contributor

@pcarleton pcarleton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the changes! one more thing

authorizationCode?: string;
scope?: string;
}): Promise<AuthResult> {
const metadata = await discoverOAuthMetadata(serverUrl);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey sorry missed this on the first go through, but we'll want to change this to be backwards compatible. Not all servers will support the new metadata endpoint immediately, so we need to try the new metadata path, and if that doesn't bear fruit, fall back to calling discoverOAuthMetadata(serverUrl)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it!
Thank you for pointing it out!

@pcarleton
Copy link
Contributor

(reviewed offline w/ @ihrpr , merging this one)

thanks again @0Itsuki0 !

@pcarleton pcarleton merged commit 69dbfac into modelcontextprotocol:main May 21, 2025
2 checks passed
const resourceMetadata = await discoverOAuthProtectedResourceMetadata(
resourceMetadataUrl || serverUrl);

if (resourceMetadata.authorization_servers && resourceMetadata.authorization_servers.length > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like we could possibly expose a better interface in this scenario - perhaps a function on the provider that would be called when there is more than one authorization server returned from the protected resource metadata that would pass in the array of servers and utilize the one returned from the function. Happy to PR this in if you feel like it makes sense!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants