You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tracked by umbrella #338. Client-side scope accumulation is covered by existing #322.
Spec summary
Aligns 403 insufficient_scope responses with RFC 6750 §3.1 — servers report only scopes needed for the current operation, NOT the union of previously granted. Clients are responsible for computing the union of (previously requested ∪ newly challenged) scopes on step-up re-authorization.
PHP SDK changes
src/Server/Transport/Http/OAuth/ 403 responses must emit ONLY the scopes required for the requested operation in WWW-Authenticate: Bearer error="insufficient_scope" scope="...".
Audit current middleware — likely needs adjustment if it emits a cumulative scope set.
I'd like to work on this. I checked the current main, and most of the server-side SEP-2350 path is already in place: JwtTokenValidator::requireScopes() puts the operation's full required scope set on the 403 result, and AuthorizationMiddleware prefers those result scopes.
The remaining edge case is AuthorizationResult::forbidden() without scopes. AuthorizationMiddleware::resolveScopes() then falls back to the resource-wide scopes_supported, so a 403 can advertise unrelated scopes instead of the requirements for the current operation.
I propose keeping the scopes_supported fallback for initial 401 challenges, while making 403 challenges use only scopes explicitly carried by AuthorizationResult. If a custom validator returns a 403 without scopes, the header would omit scope rather than infer it from PRM. This preserves the current public factory and is allowed by RFC 6750, where the 403 scope attribute is optional.
I'd cover explicit per-operation scopes, omitted scope on a scope-less 403, and unchanged 401 fallback behavior. Does that match the intended scope for this issue?
Already correctly scoped since the OAuth middleware landed in #221 — JwtTokenValidator::requireScopes() reports only the scopes required for the current operation, never a cumulative set. No change needed.
Activity
wWzZb commentedon Aug 14, 2026
I'd like to work on this. I checked the current
main, and most of the server-side SEP-2350 path is already in place:JwtTokenValidator::requireScopes()puts the operation's full required scope set on the 403 result, andAuthorizationMiddlewareprefers those result scopes.The remaining edge case is
AuthorizationResult::forbidden()without scopes.AuthorizationMiddleware::resolveScopes()then falls back to the resource-widescopes_supported, so a 403 can advertise unrelated scopes instead of the requirements for the current operation.I propose keeping the
scopes_supportedfallback for initial 401 challenges, while making 403 challenges use only scopes explicitly carried byAuthorizationResult. If a custom validator returns a 403 without scopes, the header would omitscoperather than infer it from PRM. This preserves the current public factory and is allowed by RFC 6750, where the 403scopeattribute is optional.I'd cover explicit per-operation scopes, omitted scope on a scope-less 403, and unchanged 401 fallback behavior. Does that match the intended scope for this issue?
chr-hertel commentedon Aug 19, 2026
Already correctly scoped since the OAuth middleware landed in #221 —
JwtTokenValidator::requireScopes()reports only the scopes required for the current operation, never a cumulative set. No change needed.