{"record":{"id":"ab0a08e6424bfd7b","repo":"spring-projects/spring-security","slug":"invalid-scope-ab0a08","errorCode":"invalid_scope","errorMessage":"Invalid Client Registration: scope","messagePattern":"Invalid Client Registration: scope","errorType":"error_code","errorClass":"OAuth2AuthenticationException","httpStatus":null,"severity":"error","filePath":"oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientRegistrationAuthenticationValidator.java","lineNumber":225,"sourceCode":"\t\t\t}\n\t\t\tthrow createException(\"invalid_client_metadata\", OAuth2ClientMetadataClaimNames.JWKS_URI);\n\t\t}\n\t}\n\n\tprivate static void validateJwkSetUriSimple(OAuth2ClientRegistrationAuthenticationContext authenticationContext) {\n\t\t// No validation. Preserves prior behavior.\n\t}\n\n\tprivate static void validateScope(OAuth2ClientRegistrationAuthenticationContext authenticationContext) {\n\t\tOAuth2ClientRegistrationAuthenticationToken clientRegistrationAuthentication = authenticationContext\n\t\t\t.getAuthentication();\n\t\tList<String> scopes = clientRegistrationAuthentication.getClientRegistration().getScopes();\n\t\tif (!CollectionUtils.isEmpty(scopes)) {\n\t\t\tif (LOGGER.isDebugEnabled()) {\n\t\t\t\tLOGGER.debug(LogMessage.format(\n\t\t\t\t\t\t\"Invalid request: scope must not be set during Dynamic Client Registration ('%s')\", scopes));\n\t\t\t}\n\t\t\tthrow createException(OAuth2ErrorCodes.INVALID_SCOPE, OAuth2ClientMetadataClaimNames.SCOPE);\n\t\t}\n\t}\n\n\tprivate static void validateScopeSimple(OAuth2ClientRegistrationAuthenticationContext authenticationContext) {\n\t\t// No validation. Preserves prior behavior.\n\t}\n\n\tprivate static boolean isUnsafeScheme(String scheme) {\n\t\treturn \"javascript\".equalsIgnoreCase(scheme) || \"data\".equalsIgnoreCase(scheme)\n\t\t\t\t|| \"vbscript\".equalsIgnoreCase(scheme);\n\t}\n\n\tprivate static OAuth2AuthenticationException createException(String errorCode, String fieldName) {\n\t\tOAuth2Error error = new OAuth2Error(errorCode, \"Invalid Client Registration: \" + fieldName, ERROR_URI);\n\t\tthrow new OAuth2AuthenticationException(error);\n\t}\n\n}","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientRegistrationAuthenticationValidator.java#L207-L243","documentation":"Dynamic Client Registration (RFC 7591) as implemented here does not allow the client to pre-specify scopes: validateScope throws invalid_scope for the scope claim if the registration request contains a non-empty scope list. The authorization server controls scopes itself; a client registration carrying scope is rejected.","triggerScenarios":"POSTing a client registration JSON that includes a 'scope' field (e.g. \"scope\": \"message.read message.write\") to the registration endpoint when strict validation is enabled.","commonSituations":"Migrating from other OAuth2 servers (e.g. Keycloak, Okta) where scope in registration is allowed; copying authorization-request style payloads into the registration request; templated registration clients that always include scope.","solutions":["Remove the 'scope' field from the client registration request body","If per-client scopes are needed, configure the authorization server to assign scopes upon registration (custom client mapping / RegistrationClientScope) instead of the request","Verify which validator mode the server runs (validateScope vs validateScopeSimple — the simple variant preserves prior permissive behavior)"],"exampleFix":"// before\n{\"client_name\": \"demo\", \"redirect_uris\": [\"https://app/cb\"], \"scope\": \"message.read\"}\n// after\n{\"client_name\": \"demo\", \"redirect_uris\": [\"https://app/cb\"]}","handlingStrategy":"validation","validationCode":"if (registrationJson.has(\"scope\") && !registrationJson.isNull(\"scope\")) throw new IllegalArgumentException(\"scope must not be sent in dynamic client registration\");","typeGuard":"boolean scopeFreeRegistration(java.util.Map<String,Object> body) {\n    return body.get(\"scope\") == null || body.get(\"scope\").toString().isEmpty();\n}","tryCatchPattern":"catch (OAuth2ErrorResponseException e) { if (\"invalid_scope\".equals(e.getError().getErrorCode())) { /* drop the scope field and retry */ } }","preventionTips":["Omit the scope field entirely from RFC 7591 registration payloads","Configure scopes server-side (custom registration mapping) rather than in the request","Strip scope from migrated registration templates coming from other OAuth2 servers"],"tags":["oauth2","client-registration","scope","rfc7591"],"backgroundTag":"invalid-argument-value","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}