spring-projects/spring-security · error · OAuth2AuthenticationException
invalid_token
invalid_token
Error message
Unable to authenticate the DPoP-bound access token.
What it means
DPoPAuthenticationProvider.authenticate() first authenticates the bearer access token with the delegate JwtAuthenticationProvider/OpaqueTokenAuthenticationProvider. If that delegate returns null (or a result that is not an AbstractOAuth2TokenAuthenticationToken), the provider cannot proceed to DPoP proof verification and throws OAuth2AuthenticationException with error code invalid_token and message 'Unable to authenticate the DPoP-bound access token.'
Source
Thrown at oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/DPoPAuthenticationProvider.java:84
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
DPoPAuthenticationToken dPoPAuthenticationToken = (DPoPAuthenticationToken) authentication;
BearerTokenAuthenticationToken accessTokenAuthenticationRequest = new BearerTokenAuthenticationToken(
dPoPAuthenticationToken.getAccessToken());
Authentication accessTokenAuthenticationResult = this.tokenAuthenticationManager
.authenticate(accessTokenAuthenticationRequest);
AbstractOAuth2TokenAuthenticationToken<OAuth2Token> accessTokenAuthentication = null;
if (accessTokenAuthenticationResult instanceof AbstractOAuth2TokenAuthenticationToken) {
accessTokenAuthentication = (AbstractOAuth2TokenAuthenticationToken) accessTokenAuthenticationResult;
}
if (accessTokenAuthentication == null) {
OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_TOKEN,
"Unable to authenticate the DPoP-bound access token.", null);
throw new OAuth2AuthenticationException(error);
}
OAuth2AccessTokenClaims accessToken = new OAuth2AccessTokenClaims(accessTokenAuthentication.getToken(),
accessTokenAuthentication.getTokenAttributes());
DPoPProofContext dPoPProofContext = DPoPProofContext.withDPoPProof(dPoPAuthenticationToken.getDPoPProof())
.accessToken(accessToken)
.method(dPoPAuthenticationToken.getMethod())
.targetUri(dPoPAuthenticationToken.getResourceUri())
.build();
JwtDecoder dPoPProofVerifier = this.dPoPProofVerifierFactory.createDecoder(dPoPProofContext);
try {
dPoPProofVerifier.decode(dPoPProofContext.getDPoPProof());
}
catch (Exception ex) {
OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_DPOP_PROOF);
throw new OAuth2AuthenticationException(error, ex);View on GitHub (pinned to 96852e8860)
Solutions
- Fix the underlying access-token failure first (decode the token to see why it is rejected: signature, expiry, issuer, audience)
- Ensure the delegate (JwtAuthenticationProvider or OpaqueTokenAuthenticationProvider) is correctly configured with the right decoder/introspector
- Verify the client is sending a valid, unexpired DPoP-bound access token
- Check that DPoPAuthenticationProvider is registered after the token provider in the OAuth2ResourceServer configuration
Example fix
// before
http.oauth2ResourceServer(rs -> rs.jwt());
// after
http.oauth2ResourceServer(rs -> rs.jwt()
.jwtAuthenticationProvider(new DPoPAuthenticationProvider(jwtAuthProvider, dPoPProofVerifier))); Defensive patterns
Strategy: try-catch
Validate before calling
// resource server: confirm decoder config before wiring DPoP // assert issuer/jwkSetUri reachable and algorithms match the AS
Try / catch
try {
authenticationManager.authenticate(new BearerTokenAuthenticationToken(token));
} catch (OAuth2AuthenticationException e) {
if ("invalid_token".equals(e.getError().getErrorCode())) {
log.warn("DPoP-bound access token rejected: {}", e.getError().getDescription());
}
throw e;
} Prevention
- Keep the delegate token provider correctly configured (decoder/introspector) for the issuer
- Monitor token expiry and refresh before calls to DPoP-protected endpoints
- Verify with a known-good token that delegated authentication works before enabling DPoP
When it happens
Trigger: The DPoP-bound access token itself fails delegated authentication (invalid JWT, expired, wrong issuer/audience) so the delegate yields null; the DPoPAuthenticationProvider is wired with a delegate that cannot authenticate the presented token type.
Common situations: Resource server configured for DPoP but the JWT decoder rejects the token upstream; token expired or revoked; the delegate provider's decoder/introspector misconfigured for the issuer; clients sending a non-DPoP token to a DPoP-protected endpoint.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/d58c2148d799bb4f.
Report an issue: GitHub.