Repository navigation
Conversation
|
@bolinfest is on triage rotation this week and is the reviewer for this one. Automated classification did not run for this one, so it needs a full manual pass. Automated triage. Labels are a first pass and the assigned maintainer has the final say. |
|
@stefanoamorelli, was the scope union in #888 intended to apply to initial login too, or mainly to step-up authorization? For example, an initial challenge requesting This PR adds a separate initial-login selector to preserve the existing union behavior. Would you prefer that approach, or changing the existing selector? |
There was a problem hiding this comment.
Thanks for addressing my feedback, @zamoshchin-openai. Merging now!
An MCP server can challenge an initial request with
scope="mcp.read"while its protected-resource metadata advertisesscopes_supported: ["mcp.read", "mcp.write"]. Usingselect_scopes()for that login requests both scopes, even though the challenge only asks for read access. This can introduce unnecessary consent or aninvalid_scoperejection when the client is not permitted to request the additional scope.The MCP scope-selection guidance recommends preferring the initial challenge and using protected-resource metadata when that challenge provides no scopes. RMCP already discovers this information, but its existing selector intentionally accumulates scopes and its discovery result does not expose the separate scope sources. Clients therefore lack a way to choose initial-login precedence using the existing discovery APIs.
Add the opt-in
AuthorizationManager::select_initial_scopes()API so callers can use that precedence without implementing discovery themselves or changingselect_scopes()for existing consumers. It prefers the initial resource challenge, then protected-resource metadata, using only caller-provided defaults when neither supplies scopes. It deduplicates scopes and preservesoffline_accesshandling.AuthorizationRequest::with_initial_scope_selection()exposes the same opt-in throughOAuthStateandAuthorizationSession; automatic authorization keeps the existing policy by default, and nonempty explicit scopes retain precedence.Initial scopes are recorded separately so scope-only challenges work, later metadata challenges cannot replace the resource request's scopes, and repeated discovery does not reuse stale initial scopes.
Validation:
cargo +1.97.1 test -p rmcp --lib --features auth,client,reqwest transport::auth::tests:: --quiet: 228 passed.cargo +1.97.1 test -p rmcp --doc --features auth,client,reqwest select_initial_scopes --quiet: passed.cargo +1.96 clippy -p rmcp --all-targets --all-features -- -D warnings: passed.cargo +nightly fmt --all -- --check: passed.