spring-projects/spring-security · error · OAuth2AuthenticationException
authorization_request_not_found
authorization_request_not_found
Error message
authorization_request_not_found
What it means
During the OAuth2 callback the filter removes the stored OAuth2AuthorizationRequest (typically from the session via HttpSessionOAuth2AuthorizationRequestRepository). If no stored request exists, the callback is unsolicited and this error with code authorization_request_not_found is thrown.
Source
Thrown at oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilter.java:178
Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null");
this.clientRegistrationRepository = clientRegistrationRepository;
this.authorizedClientRepository = authorizedClientRepository;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
MultiValueMap<String, String> params = OAuth2AuthorizationResponseUtils.toMultiMap(request.getParameterMap());
if (!OAuth2AuthorizationResponseUtils.isAuthorizationResponse(params)) {
OAuth2Error oauth2Error = new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST);
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
}
OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestRepository
.removeAuthorizationRequest(request, response);
if (authorizationRequest == null) {
OAuth2Error oauth2Error = new OAuth2Error(AUTHORIZATION_REQUEST_NOT_FOUND_ERROR_CODE);
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
}
String registrationId = authorizationRequest.getAttribute(OAuth2ParameterNames.REGISTRATION_ID);
Assert.hasText(registrationId, "registrationId cannot be empty");
ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId(registrationId);
if (clientRegistration == null) {
OAuth2Error oauth2Error = new OAuth2Error(CLIENT_REGISTRATION_NOT_FOUND_ERROR_CODE,
"Client Registration not found with Id: " + registrationId, null);
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
}
// @formatter:off
String redirectUri = UriComponentsBuilder.fromUriString(UrlUtils.buildFullRequestUrl(request))
.replaceQuery(null)
.build()
.toUriString();
// @formatter:on
OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponseUtils.convert(params,
redirectUri);
Object authenticationDetails = this.authenticationDetailsSource.buildDetails(request);View on GitHub (pinned to 96852e8860)
Solutions
- Use sticky sessions or a shared session store (e.g. Spring Session with Redis/JDBC) across all nodes
- Verify the JSESSIONID cookie survives the redirect to the IdP (check SameSite=None; Secure when IdP is cross-site)
- Have users restart the login flow from /oauth2/authorization/{registrationId}; clear stale cookies
- If callbacks are intentionally unsolicited, configure the authorizationRequestRepository appropriately or relax the filter per Spring Security docs on unsolicited responses
Example fix
// before // multiple nodes, in-memory sessions, round-robin LB // after // enable Spring Session <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency>
Defensive patterns
Strategy: try-catch
Try / catch
catch (OAuth2AuthenticationException e) {
if ("authorization_request_not_found".equals(e.getError().getErrorCode())) {
// redirect user to /oauth2/authorization/{id} to restart login
}
} Prevention
- Use sticky sessions or Spring Session (Redis/JDBC) across nodes
- Check cookie flags (SameSite/Secure) so JSESSIONID survives the IdP redirect
- Invalidate stale bookmarks of redirect URIs and restart login from the app
When it happens
Trigger: The redirect_uri is hit with code/state parameters but the session that started login is gone: cookie lost, session expired, server restarted without sticky sessions, or the callback arrives in a different browser/session.
Common situations: Multiple backend nodes without sticky sessions or shared session store; SameSite/cookie policies dropping JSESSIONID on cross-site redirect; users clicking an old callback link from history; cookies blocked by the browser.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- invalid_request
- Unable to create an {OAuth2AuthorizedClientManager} bean. Ex
- invalid_dpop_proof
- invalid_scope
- oidc_provider_not_configured
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/b3435636063678b7.
Report an issue: GitHub.