spring-projects/spring-security · error · InvalidBearerTokenException
invalid_token
invalid_token
Error message
Invalid token
What it means
JwtAuthenticationProvider.getJwt() decodes the bearer token; when the decoder throws BadJwtException (structurally invalid JWT: bad signature format, unsupported alg, malformed claims), it is translated to InvalidBearerTokenException with message 'Invalid token' (or the BadJwtException's message), producing an OAuth2 invalid_token response. Other JwtExceptions (server-side issues like key fetch failures) become AuthenticationServiceException instead.
Source
Thrown at oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationProvider.java:104
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
BearerTokenAuthenticationToken bearer = (BearerTokenAuthenticationToken) authentication;
Jwt jwt = getJwt(bearer);
AbstractAuthenticationToken token = this.jwtAuthenticationConverter.convert(jwt);
Assert.notNull(token, "token cannot be null");
if (token.getDetails() == null) {
token.setDetails(bearer.getDetails());
}
this.logger.debug("Authenticated token");
return token;
}
private Jwt getJwt(BearerTokenAuthenticationToken bearer) {
try {
return this.jwtDecoder.decode(bearer.getToken());
}
catch (BadJwtException failed) {
this.logger.debug("Failed to authenticate since the JWT was invalid");
throw new InvalidBearerTokenException((failed.getMessage() != null) ? failed.getMessage() : "Invalid token",
failed);
}
catch (JwtException failed) {
throw new AuthenticationServiceException(
(failed.getMessage() != null) ? failed.getMessage() : "Invalid token", failed);
}
}
@Override
public boolean supports(Class<?> authentication) {
return BearerTokenAuthenticationToken.class.isAssignableFrom(authentication);
}
public void setJwtAuthenticationConverter(
Converter<Jwt, ? extends AbstractAuthenticationToken> jwtAuthenticationConverter) {
Assert.notNull(jwtAuthenticationConverter, "jwtAuthenticationConverter cannot be null");
this.jwtAuthenticationConverter = jwtAuthenticationConverter;
}View on GitHub (pinned to 96852e8860)
Solutions
- Inspect the debug log line 'Failed to authenticate since the JWT was invalid' and the nested BadJwtException message for the root cause
- Have the client obtain a fresh token from the Authorization Server
- Decode the token at jwt.io to check header/payload structure
- Verify the resource server decoder config (jwkSetUri reachable, algorithms) matches the issuer
Defensive patterns
Strategy: try-catch
Validate before calling
// check token has 3 segments and is not visibly expired before calling
if (jwt.split("\\.").length != 3) throw new IllegalStateException("Malformed JWT"); Try / catch
try {
Jwt jwt = decoder.decode(token);
} catch (InvalidBearerTokenException e) {
// token structurally invalid — do not retry, re-authenticate
throw new UnauthorizedException("Token rejected", e);
} catch (AuthenticationServiceException e) {
// server-side issue (e.g. JWKS fetch failed) — safe to retry
} Prevention
- Distinguish BadJwtException (client token bad) from JwtException (server config issue) in logs
- Keep JWKS endpoint reachable and cache-refresh healthy
- Refresh tokens client-side before expiry
- Never hand-edit or truncate tokens (proxy URL-encoding issues)
When it happens
Trigger: Bearer token fails JwtDecoder.decode() with BadJwtException — malformed token, unsupported algorithm, expired/malformed claims depending on decoder — during JwtAuthenticationProvider.authenticate().
Common situations: Client sending a truncated or hand-edited JWT; expired token surfaced as 'Invalid token' by some decoders; issuer key rotation invalidating signatures; copy-paste errors losing part of the Authorization header value.
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/629171041435de06.
Report an issue: GitHub.