Skip to content

[OAuth] Request all supported scopes when not using the OAuth debugger #455

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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

leblancfg
Copy link

@leblancfg leblancfg commented May 27, 2025

Adds a "scope" section to the Authorization URL in the OAuth flow, matching the OAuth debugger behaviour.

Motivation and Context

When using the OAuth debugger, it adds the scope search parameter with the ones provided in the scopes_supported key.

However, the main "connect" button does not pass them to the MCP SDK and they are missing from the call. Some OAuth providers and setups will require you to have them and the OAuth flow fails in these cases. This change fixes that.

Closes #454

How Has This Been Tested?

Local tests for a streamable HTTP MCP server were successful when using the OAuth debugger. The URL generated in the debugger is (scroll to see the end):

https://oauth.example.com/oauth/authorize?response_type=code&client_id=$CLIENT_ID&code_challenge=$CODE_CHALLENGE&code_challenge_method=S256&redirect_uri=http%3A%2F%2F127.0.0.1%3A6274%2Foauth%2Fcallback%2Fdebug&scope=read+write

but the "Connect" button currently returns:

https://oauth.example.com/oauth/authorize?response_type=code&client_id=$CLIENT_ID&code_challenge=$CODE_CHALLENGE&code_challenge_method=S256&redirect_uri=http%3A%2F%2F127.0.0.1%3A6274%2Foauth%2Fcallback%2Fdebug

This PR makes it so scopes are passed if the scopes_supported key is present in the authorization server metadata.

Breaking Changes

MCP servers that rely on implicitly using default scopes will now have them explicitly set, and those scopes might differ.

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

leblancfg added 2 commits May 27, 2025 16:59
When using the OAuth debugger, it correctly adds the scope search
parameter with the ones provided in the `scopes_supported` key.

However, the main "connect" button does not pass them to the MCP SDK and
they are missing from the call. Some OAuth providers and setups will
require you to have them and the OAuth flow fails in these cases. This
change fixes that.
@dr3s
Copy link
Contributor

dr3s commented May 29, 2025

opened modelcontextprotocol/typescript-sdk#564 because it seems all clients that I tested need this.

@leblancfg
Copy link
Author

leblancfg commented May 30, 2025

it seems all clients that I tested need this

This would indeed be simpler.

However, I was under the impression scopes_supported is not meant to indicate that an OAuth client should request all scopes in the list. I think this is an OK assumption to make in the inspector (meant for debugging), but I didn't think it was an OK assumption to make at the SDK layer.

Related issue in Spring Boot, where this used to be the default and was changed to i.e.

if metadata.getScopes() contains openid then
default to openid, profile, email
else
default to openid

maybe this is a better default, even in the inspector?

@dr3s
Copy link
Contributor

dr3s commented Jun 2, 2025

unfortunately, there's no way for the Client to know the correct scope to request without using the oauth server or registered client metadata. MS Entra requires the scope to be passed and the minimal scopes suggested won't be sufficient until we have some way of triggering consent for additional scopes when privileges need to be escalated.

@cliffhall
Copy link
Contributor

unfortunately, there's no way for the Client to know the correct scope to request without using the oauth server or registered client metadata. MS Entra requires the scope to be passed and the minimal scopes suggested won't be sufficient until we have some way of triggering consent for additional scopes when privileges need to be escalated.

In the Spring Boot example, it was a convincing argument that defaulting to all scopes is maybe not as good as defaulting to none. I have to agree with @leblancfg that in the Inspector, it would be less problematic than in the SDK.

@cliffhall cliffhall added the waiting on submitter Waiting for the submitter to provide more info label Jun 2, 2025
@leblancfg
Copy link
Author

@cliffhall I see the "waiting on submitter" tag, anything in particular you'd like me to clarify?

@cliffhall
Copy link
Contributor

cliffhall commented Jun 3, 2025

@cliffhall I see the "waiting on submitter" tag, anything in particular you'd like me to clarify?

Really waiting to hear @pcarleton's take. When closing the counterpart PR in the SDK, he said he'd follow up here.

I think it's probably ok to request all scopes in the Inspector, but maybe the another solution is a configuration panel field that lets you put in the scopes you want to request, and if nothing is there, we request none.

@dr3s
Copy link
Contributor

dr3s commented Jun 4, 2025

@cliffhall a configurable UI panel may be ok for inspector but I can't see it being suitable for other MCP clients. The configuration would be too technical for most users. Even for inspector, users wouldn't understand some scope unless they were also the MCP server dev.

@cliffhall
Copy link
Contributor

@cliffhall a configurable UI panel may be ok for inspector but I can't see it being suitable for other MCP clients. The configuration would be too technical for most users. Even for inspector, users wouldn't understand some scope unless they were also the MCP server dev.

@dr3s You're right, for other MCP clients a scopes field would not be appropriate at all. But this tool is primarily used by MCP server devs to test their own servers. If you wanted to ensure that your server only authorized and allowed interaction with the requested scopes, this would probably be the easiest way to do it.

@pcarleton
Copy link
Contributor

pcarleton commented Jun 9, 2025

Hey sorry for the delay!

Here's the issue we run into, imagine an example like this:

  • supported_scopes: [read, write, admin]
  • implicit required default scope read that the client doesn't know about unless they read the server's docs
  • user attempts auth with scope omitted, gets invalid_scope error
  • user attempts auth again with read write admin as scope parameter... more privilege than it needs. (problem is the client doesn't know what to pick here.)

The best we can do with the current spec is to rely on the WWW-Authenticate header to provide a scope. So the order of preference would be:

  1. Use the scope included during the initial 401 WWW-Authenticate header response
  2. Omit scope otherwise, and let the server give defaults
  3. include all of supported_scopes as a final fallback after ^ we get invalid_scope

This change jumps straight to (3), but also (1) isn't supported in the SDK yet.

I think we could either:
a. Merge this, so it's consistent with the debugger, and then fix them both later once the SDK supports (1)
b. Not merge this (and then also "undo" the debugger scope thing), and wait to fix them until SDK supports (1)
c. Not merge this, and require manually inputting scopes if you don't want "default".

I'm slightly in favor of (a) since it should reduce confusion and increase compatibility. The biggest downside would be having it be in the inspector and having that be "contagious" where others start using the pattern and it becomes the norm to request all scopes.

@cliffhall
Copy link
Contributor

The best we can do with the current spec is to rely on the WWW-Authenticate header to provide a scope. So the order of preference would be:

  1. Use the scope included during the initial 401 WWW-Authenticate header response
  2. Omit scope otherwise, and let the server give defaults
  3. include all of supported_scopes as a final fallback after ^ we get invalid_scope

This change jumps straight to (3), but also (1) isn't supported in the SDK yet.

I think we could either: a. Merge this, so it's consistent with the debugger, and then fix them both later once the SDK supports (1) b. Not merge this (and then also "undo" the debugger scope thing), and wait to fix them until SDK supports (1) c. Not merge this, and require manually inputting scopes if you don't want "default".

I'm slightly in favor of (a) since it should reduce confusion and increase compatibility. The biggest downside would be having it be in the inspector and having that be "contagious" where others start using the pattern and it becomes the norm to request all scopes.

Thanks for weighing in, @pcarleton. I agree the that getting all scopes now but moving quickly to amend when we have a better option sounds like the right thing.

@cliffhall
Copy link
Contributor

@leblancfg this needs a prettier-fix run to pass CI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
waiting on submitter Waiting for the submitter to provide more info
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Connection with OAuth doesn't include scopes
4 participants