Return granted scope on token exchange, fix solving-times:write role check - #184
Open
puzzlerushse wants to merge 1 commit into
Open
Conversation
…check league/oauth2-server's default token response never includes which scopes were actually granted (BearerTokenResponse::getExtraParams returns []). Nothing wrong with that as shipped, but a consuming app that wants to detect a stale, pre-scope-expansion authorization (e.g. re-checking for a write scope before attempting a write, rather than attempting a call that will 403) has nothing to check the response against. ScopeAwareBearerTokenResponse adds the scope back via the response_type_class extension point already supported by league/oauth2-server-bundle - picked up automatically by the existing Security/** service glob in config/services.php, no explicit service registration needed. Bundled with a related but independent bug in already-shipped code: CreateSolvingTimeInput/UpdateSolvingTimeInput's write-scope security check compares against ROLE_OAUTH2_SOLVING_TIMES:WRITE (underscore), but the role oauth2-server actually grants is built by uppercasing the scope string verbatim (OAuth2Token.php: strtoupper($rolePrefix . $scope), no punctuation normalization) - so a solving-times:write scope produces ROLE_OAUTH2_SOLVING-TIMES:WRITE (hyphen). solving-times is the only hyphenated scope in the system, which is presumably why this was never caught: nothing else has ever exercised this path. An OAuth-scope-authenticated write to /me/solving-times has likely never worked; PAT-based writes are unaffected (ROLE_PAT is checked independently). Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two independent, small fixes bundled together since they touch the same file group:
1. Token response never includes granted scope
league/oauth2-server's default response never includes which scopes were actually granted (BearerTokenResponse::getExtraParamsreturns[]). Nothing wrong with that as shipped, but a consuming app that wants to detect a stale, pre-scope-expansion authorization (e.g. re-checking for a write scope before attempting a write, rather than attempting a call that will 403) has nothing to check the response against.ScopeAwareBearerTokenResponseadds the scope back via theresponse_type_classextension point already supported byleague/oauth2-server-bundle. It's picked up automatically by the existingSecurity/**service glob inconfig/services.php— no explicit service registration needed.2. Wrong role name checked for
solving-times:writeCreateSolvingTimeInput/UpdateSolvingTimeInput's write-scope security check compares againstROLE_OAUTH2_SOLVING_TIMES:WRITE(underscore), but the roleoauth2-serveractually grants is built by uppercasing the scope string verbatim (OAuth2Token.php:strtoupper($rolePrefix . $scope), no punctuation normalization) — so asolving-times:writescope producesROLE_OAUTH2_SOLVING-TIMES:WRITE(hyphen).solving-timesis the only hyphenated scope in the system, which is presumably why this was never caught — nothing else has ever exercised this exact path. An OAuth-scope-authenticated write to/me/solving-timeshas likely never worked; PAT-based writes are unaffected (ROLE_PATis checked independently in the sameorexpression).Test plan
solving-times:writecan now successfullyPOST/PUT/api/v1/me/solving-times/oauth2/token) now includes ascopefield listing the granted scopes