spring-projects/spring-security · error

Removed expired pushed authorization request for client id '

Error message

Removed expired pushed authorization request for client id '%s'

What it means

This warning is emitted by OAuth2AuthorizationCodeRequestAuthenticationProvider when a pushed authorization request (PAR, RFC 9126) referenced via request_uri is retrieved from the authorization service but its expiresAt timestamp has passed. The provider removes the stored pushed authorization request, effectively invalidating it, and throws an OAuth2AuthenticationException with error INVALID_REQUEST and the request_uri parameter reported as invalid.

Source

Thrown at oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProvider.java:167

			if (this.logger.isTraceEnabled()) {
				this.logger.trace("Retrieved authorization with pushed authorization request");
			}

			OAuth2AuthorizationRequest authorizationRequest = pushedAuthorization
				.getAttribute(OAuth2AuthorizationRequest.class.getName());
			Assert.notNull(authorizationRequest, "authorizationRequest cannot be null");

			if (!authorizationCodeRequestAuthentication.getClientId().equals(authorizationRequest.getClientId())) {
				throw createException(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.CLIENT_ID,
						authorizationCodeRequestAuthentication, null);
			}

			if (Instant.now().isAfter(pushedAuthorizationRequestUri.getExpiresAt())) {
				// Remove (effectively invalidating) the pushed authorization request
				this.authorizationService.remove(pushedAuthorization);
				if (this.logger.isWarnEnabled()) {
					this.logger
						.warn(LogMessage.format("Removed expired pushed authorization request for client id '%s'",
								authorizationRequest.getClientId()));
				}
				throw createException(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.REQUEST_URI,
						authorizationCodeRequestAuthentication, null);
			}

			authorizationCodeRequestAuthentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
					authorizationCodeRequestAuthentication.getAuthorizationUri(), authorizationRequest.getClientId(),
					(Authentication) authorizationCodeRequestAuthentication.getPrincipal(),
					authorizationRequest.getRedirectUri(), authorizationRequest.getState(),
					authorizationRequest.getScopes(), authorizationRequest.getAdditionalParameters());
		}

		RegisteredClient registeredClient = this.registeredClientRepository
			.findByClientId(authorizationCodeRequestAuthentication.getClientId());
		if (registeredClient == null) {
			throw createException(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.CLIENT_ID,
					authorizationCodeRequestAuthentication, null);

View on GitHub (pinned to 96852e8860)

Solutions

  1. Push the authorization request again (POST to the par endpoint) immediately before redirecting the user to the authorization endpoint, so the request_uri is fresh.
  2. Increase OAuth2AuthorizationServerConfigurer's pushedAuthorizationRequestTimeToLive if legitimate flows need longer.
  3. Fix client flow orchestration so the authorize redirect happens right after obtaining the request_uri (no intermediate user detours).
  4. Handle the invalid_request error on request_uri by transparently re-pushing the request and retrying the redirect.

Example fix

// before: request_uri created long before redirect
String requestUri = pushRequest();
scheduleRedirectAfterUserReview(requestUri); // may exceed TTL
// after: push right before redirect
String requestUri = pushRequest();
response.sendRedirect(authorizeUrl(requestUri));
Defensive patterns

Strategy: retry

Validate before calling

// validate request_uri freshness before redirecting
Instant pushedAt = getPushedRequestTime(requestUri);
if (pushedAt.plus(parTtl).isBefore(Instant.now())) {
  requestUri = pushAuthorizationRequest(); // re-push before it is rejected
}

Try / catch

try {
  redirectToAuthorize(requestUri);
} catch (OAuth2AuthenticationException e) {
  if ("invalid_request".equals(e.getError().getErrorCode())) {
    // re-push the PAR and retry with a fresh request_uri
    requestUri = pushAuthorizationRequest();
    redirectToAuthorize(requestUri);
  }
}

Prevention

When it happens

Trigger: A client is redirected to the authorization endpoint with a request_uri obtained from a PAR POST, but more than the configured pushedAuthorizationRequestTimeToLive has elapsed before the authorization endpoint is hit. The lookup finds the expired authorization and takes this branch.

Common situations: Users sitting on a pre-built authorize URL beyond the PAR TTL (often 30-90s default), slow redirects through an external IdP chain, or stale bookmarked/deep-linked authorize URLs reused across sessions.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/a852bf56d8e14501. Report an issue: GitHub.