Repository navigation
Conversation
…251) Spring Authorization Server only checks that a requested scope is registered for the client, whatever the grant. ESPI keeps customer data and administrative tokens apart, so: - client_credentials cannot be granted an ESPI customer data scope (any FB=... other than the FB=36_40 registration-token renewal scope); - authorization_code cannot be granted an administrative scope (ThirdParty_Admin_Access, DataCustodian_Admin_Access, FB=36_40, authserver.admin, client.create). The client receives invalid_scope at its redirect URI, as Spring does for its own scope check. EspiGrantScopePolicy runs after Spring's default validators on the token and authorization endpoints. Tested with unit tests and a Docker-backed SecurityIntegrationTest case using a client registered for both grants. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Data Custodian parses scopes tolerantly (any segment order, trimmed, case-insensitive FB key), so a prefix check on "FB=" could be bypassed with a different spelling, and Upload_Admin_Access was missing from the administrative list. Both rules now fail closed: - client_credentials: only the exact administrative scope strings, including Upload_Admin_Access; - authorization_code: only openid/profile, or a scope that parses like EspiScope to Function Blocks other than the reserved 36 and 40. Unparseable or unknown scopes are rejected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5 tasks done
… introspection test The GHSA-mh65 test minted a client_credentials token for the placeholder scope FB_1, which the per-grant allowlist now rejects. It requests ThirdParty_Admin_Access instead. Co-Authored-By: Claude Opus 5.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
Part of #251. Each OAuth grant may now yield only its own kind of scope, even for a client registered for both kinds. Spring Authorization Server checks only that a requested scope is registered for the client, whatever the grant. Without this rule, a Third Party registered for
client_credentialsand a customer Function Block scope could mint a customer-data token with no customer's consent.Both rules are allowlists that fail closed:
client_credentials(client access token, renewal, infrastructure clients)ThirdParty_Admin_Access,DataCustodian_Admin_Access,Upload_Admin_Access,FB=36_40,authserver.admin,client.create400 invalid_scopeauthorization_code(customer consent)openid,profile, or a scope that parses to Function Blocks, none of them 36 or 40invalid_scoperedirected to the client's redirect URI (same as Spring's own scope error)The authorization-code check parses scopes the way the Data Custodian's
EspiScopedoes (;-separated, trimmed, case-insensitiveFBkey,_-separated integers), so a different spelling can't slip a customer scope past the token endpoint. An unparseable scope is rejected. Refresh tokens can only narrow the scopes of their original grant, so they need no rule.Changes
grant/EspiGrantScopePolicy: validators that run after Spring's defaults (OAuth2ClientCredentialsAuthenticationValidator.DEFAULT_SCOPE_VALIDATOR,OAuth2AuthorizationCodeRequestAuthenticationValidator), so the existing checks are kept.AuthorizationServerConfig: installs them on the token and authorization endpoints' providers.Not in this PR (rest of #251)
Registration granting
client_credentialsto Third Parties with server-assignedThirdParty_Admin_Access/FB=36_40, the registration access token, and the DC accepting it for ApplicationInformation. This rule is the safety net that makes grantingclient_credentialsat registration safe.Test plan
EspiGrantScopePolicyTest(27):IntervalDuration=3600;FB=4_5_15,fb=4_5_15,FB =4) rejected forclient_credentials;FB=36,fb=36_40,FB=4_36), administrative, unparseable (FB=abc) and unknown scopes rejected forauthorization_code;invalid_scoperedirect keepsredirect_uriandstate.SecurityIntegrationTest"ESPI per-grant scope policy (Registration access token: issue it on RFC 7591 registration, renew via FB=36_40, and require it for ApplicationInformation #251)" (Docker, CI): a client registered for both grants getsinvalid_scopefor a customer scope viaclient_credentialsand forThirdParty_Admin_Accessvia/oauth2/authorize, and succeeds for the scope that matches the grant🤖 Generated with Claude Code