SEP-2350: Clarify client-side scope accumulation in step-up authorization — rust-sdk implementation
Spec PR: modelcontextprotocol/modelcontextprotocol#2350
Track: Specification · Stage: accepted · Priority: P0 · Theme: Enterprise Readiness
Needs code changes: Yes (Small)
Summary
Clarifies step-up authorization scope handling:
- Servers report scopes needed for the current operation in 403 / insufficient-scope errors (RFC 6750 §3.1), not the union of previously granted scopes.
- Clients accumulate scopes: during re-authorization the client requests the union of previously requested scopes and the newly challenged scopes.
- "Authoritative" in Protected Resource Metadata means scopes required for the current operation, not the exclusive set the client should request.
Why this needs code changes in rust-sdk
The OAuth client's scope logic lives in crates/rmcp/src/transport/auth.rs on
AuthorizationManager:
select_scopes(www_authenticate_scope, default_scopes) → calls select_base_scopes(..) then add_offline_access_if_supported(..).
select_base_scopes(..) currently returns early with a single source in priority order (WWW-Authenticate scope → stored www_auth_scopes → resource_scopes (RFC 9728) → AS scopes_supported → defaults). It replaces rather than unions — so on a step-up 403 it returns only the freshly challenged scope and drops previously granted ones.
- Supporting state:
current_scopes: RwLock<Vec<String>>, scope_upgrade_attempts, ScopeUpgradeConfig, can_attempt_scope_upgrade(), get_current_scopes(), WWWAuthenticateParams::is_insufficient_scope().
Conformance currently reports auth/scope-step-up FAIL (13/14) — consistent with the
replace-not-union behavior above.
Proposed work
Affected areas
crates/rmcp/src/transport/auth.rs (AuthorizationManager::select_scopes / select_base_scopes, current_scopes).
Notes / risks
- Directly fixes a known failing conformance scenario. Good candidate to bundle with SEP-2351/2352/2468 auth work.
SEP-2350: Clarify client-side scope accumulation in step-up authorization — rust-sdk implementation
Spec PR: modelcontextprotocol/modelcontextprotocol#2350
Track: Specification · Stage: accepted · Priority: P0 · Theme: Enterprise Readiness
Needs code changes: Yes (Small)
Summary
Clarifies step-up authorization scope handling:
Why this needs code changes in rust-sdk
The OAuth client's scope logic lives in
crates/rmcp/src/transport/auth.rsonAuthorizationManager:select_scopes(www_authenticate_scope, default_scopes)→ callsselect_base_scopes(..)thenadd_offline_access_if_supported(..).select_base_scopes(..)currently returns early with a single source in priority order (WWW-Authenticate scope → storedwww_auth_scopes→resource_scopes(RFC 9728) → ASscopes_supported→ defaults). It replaces rather than unions — so on a step-up 403 it returns only the freshly challenged scope and drops previously granted ones.current_scopes: RwLock<Vec<String>>,scope_upgrade_attempts,ScopeUpgradeConfig,can_attempt_scope_upgrade(),get_current_scopes(),WWWAuthenticateParams::is_insufficient_scope().Conformance currently reports
auth/scope-step-upFAIL (13/14) — consistent with thereplace-not-union behavior above.
Proposed work
select_base_scopes(or a new wrapper), when a step-up challenge arrives, union the newly challenged scopes withcurrent_scopes(the previously requested/granted set) rather than returning a single source early.current_scopesafter a successful re-authorization so subsequent rounds keep growing the set.auth/scope-step-upto green; add unit tests covering multiple step-up rounds accumulating scopes.Affected areas
crates/rmcp/src/transport/auth.rs(AuthorizationManager::select_scopes/select_base_scopes,current_scopes).Notes / risks