{"record":{"id":"ce7d64c1c4d33148","repo":"spring-projects/spring-security","slug":"consent-required","errorCode":"consent_required","errorMessage":"OAuth 2.0 Parameter: prompt","messagePattern":"OAuth 2\\.0 Parameter: prompt","errorType":"error_code","errorClass":"OAuth2AuthorizationCodeRequestAuthenticationException","httpStatus":null,"severity":"error","filePath":"oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProvider.java","lineNumber":266,"sourceCode":"\t\t\t.authorizationUri(authorizationCodeRequestAuthentication.getAuthorizationUri())\n\t\t\t.clientId(registeredClient.getClientId())\n\t\t\t.redirectUri(authorizationCodeRequestAuthentication.getRedirectUri())\n\t\t\t.scopes(authorizationCodeRequestAuthentication.getScopes())\n\t\t\t.state(authorizationCodeRequestAuthentication.getState())\n\t\t\t.additionalParameters(authorizationCodeRequestAuthentication.getAdditionalParameters())\n\t\t\t.build();\n\t\tauthenticationContextBuilder.authorizationRequest(authorizationRequest);\n\n\t\tOAuth2AuthorizationConsent currentAuthorizationConsent = this.authorizationConsentService\n\t\t\t.findById(registeredClient.getId(), principal.getName());\n\t\tif (currentAuthorizationConsent != null) {\n\t\t\tauthenticationContextBuilder.authorizationConsent(currentAuthorizationConsent);\n\t\t}\n\n\t\tif (this.authorizationConsentRequired.test(authenticationContextBuilder.build())) {\n\t\t\tif (promptValues.contains(OidcPrompt.NONE)) {\n\t\t\t\t// Return an error instead of displaying the consent page\n\t\t\t\tthrow createException(\"consent_required\", \"prompt\", authorizationCodeRequestAuthentication,\n\t\t\t\t\t\tregisteredClient);\n\t\t\t}\n\n\t\t\tString state = DEFAULT_STATE_GENERATOR.generateKey();\n\t\t\tOAuth2Authorization authorization = authorizationBuilder(registeredClient, principal, authorizationRequest)\n\t\t\t\t.attribute(OAuth2ParameterNames.STATE, state)\n\t\t\t\t.build();\n\n\t\t\tif (this.logger.isTraceEnabled()) {\n\t\t\t\tthis.logger.trace(\"Generated authorization consent state\");\n\t\t\t}\n\n\t\t\tthis.authorizationService.save(authorization);\n\n\t\t\tif (this.logger.isTraceEnabled()) {\n\t\t\t\tthis.logger.trace(\"Saved authorization\");\n\t\t\t}\n","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProvider.java#L248-L284","documentation":"This error is thrown by the authorization code request provider when user consent is required to proceed, but the original authorization request contained prompt=none. Per OIDC, the server must not display any UI for prompt=none, so instead of rendering the consent page it returns an OAuth2 error consent_required attributed to the prompt parameter. It signals that silent authentication could not complete because the client has not yet been granted consent for the requested scopes.","triggerScenarios":"An OAuth2 authorization code request (OAuth2AuthorizationCodeRequestAuthenticationToken) includes prompt=none among its prompt values, the client is not already authorized for the requested scopes, and the authorizationConsentRequired predicate evaluates to true in OAuth2AuthorizationCodeRequestAuthenticationProvider.authenticate.","commonSituations":"Single-page or mobile apps doing silent re-authentication/token renewal with prompt=none after the user's consent expired or was revoked; a client adding new scopes that were never consented to; misconfigured RegisteredClient lacking pre-authorized scopes so consent is always required; switching identity providers or clearing authorization records in testing.","solutions":["Remove prompt=none from the authorization request (or handle the consent_required error by falling back to an interactive flow with prompt=consent or no prompt) so the user can grant consent.","Pre-authorize the client for the requested scopes so consent is no longer required (e.g. seed an authorized scope record or store OAuth2Authorization with approved scopes).","Reduce requested scopes to only those the user has already consented to.","If using a custom authorizationConsentRequired predicate, adjust it so consent is not required for already-authorized clients/scopes."],"exampleFix":"// before\nString redirect = \"/oauth2/authorize?response_type=code&client_id=my-client&scope=read&prompt=none\";\n// after (fall back to interactive consent when consent is required)\nString redirect = \"/oauth2/authorize?response_type=code&client_id=my-client&scope=read\"; // drop prompt=none, or catch consent_required and retry with prompt=consent","handlingStrategy":"try-catch","validationCode":"// before sending the request, ensure prompt=none is only used when consent is already granted\nboolean hasPromptNone = request.getPromptValues().contains(\"none\");\nboolean consentRequired = requestedScopes.stream().anyMatch(s -> !previouslyAuthorizedScopes.contains(s));\nif (hasPromptNone && consentRequired) {\n    // drop prompt=none or pre-authorize scopes; otherwise consent_required is guaranteed\n    request = request.withPrompt(PromptValue.CONSENT);\n}","typeGuard":null,"tryCatchPattern":"try {\n    authenticate(authorizationRequest);\n} catch (OAuth2AuthorizationCodeRequestAuthenticationException e) {\n    if (\"consent_required\".equals(e.getError().getErrorCode())) {\n        // retry interactively without prompt=none\n        redirectToConsentPage(stripPromptNone(originalRequest));\n    } else {\n        throw e;\n    }\n}","preventionTips":["Only use prompt=none for silent flows when the user's consent is known to still be valid","Pre-seed authorized scopes for clients that rely on silent authentication","Handle consent_required as a signal to fall back to interactive login, not as a bug","Keep requested scopes stable; adding scopes invalidates silent flow assumptions"],"tags":["oauth2","oidc","consent","prompt-none","authorization-server"],"backgroundTag":"oauth-consent-required","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"}