spring-projects/spring-security · error · BadJwtException

Unsupported algorithm of + jwt.getHeader().getAlgorithm()

Error message

Unsupported algorithm of + jwt.getHeader().getAlgorithm()

What it means

Inside the JwkSourceReactiveJwtDecoderBuilder's processor, if the decoded token is not a SignedJWT (i.e. it is an unsecured/JWE token or uses an unexpected header), the decoder cannot select a JWK for it and throws BadJwtException('Unsupported algorithm of <alg>'). It guards the jwkSource path so only JWS-signed tokens the configured algorithms apply to reach key selection.

Solutions

  1. Check the token header alg and ensure the decoder's jwsAlgorithms includes it
  2. Ensure the issuer produces SignedJWTs (signed, not encrypted or unsecured tokens)
  3. Use NimbusJwtDecoder/NimbusReactiveJwtDecoder withJweDecoder support if encrypted tokens are the real input
  4. Regenerate a valid signed test token from the Authorization Server

Example fix

// before
JWSAlgorithm expected = JWSAlgorithm.HS256; // token actually uses ES256
// after
JWSAlgorithm expected = JWSAlgorithm.ES256;
NimbusReactiveJwtDecoder decoder = NimbusReactiveJwtDecoder.withJwkSource(jwkSource)
    .jwsAlgorithm(SignatureAlgorithm.ES256).build();
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm token is a SignedJWT with expected alg before calling the decoder
String[] parts = jwt.split("\\.");
if (parts.length != 3) throw new IllegalArgumentException("Not a JWS (3 segments expected)");

Try / catch

try {
    Jwt jwt = decoder.decode(token);
} catch (BadJwtException e) {
    log.warn("Token not a supported signed JWT: {}", e.getMessage());
    throw new UnauthorizedException("Unsupported token type/algorithm");
}

Prevention

When it happens

Trigger: Calling NimbusReactiveJwtDecoder.withJwkSource(...) and feeding it a token whose header alg does not match the configured jwsAlgorithms (so Nimbus decodes it as something other than a SignedJWT path), or an unsecured/alg=none or encrypted token is passed to a decoder meant for signed JWS tokens.

Common situations: Sending JWE (encrypted) tokens to a decoder expecting signed JWTs; an issuer switching to alg=none or a non-signing token type; misconfigured jwsAlgorithms so the processor falls through to this throw; testing with hand-crafted tokens.

Related errors


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

Appendix: source

Thrown at oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoder.java:943

		Converter<JWT, Mono<JWTClaimsSet>> processor() {
			JWKSecurityContextJWKSet jwkSource = new JWKSecurityContextJWKSet();
			JWSKeySelector<JWKSecurityContext> jwsKeySelector = new JWSVerificationKeySelector<>(this.jwsAlgorithm,
					jwkSource);
			DefaultJWTProcessor<JWKSecurityContext> jwtProcessor = new DefaultJWTProcessor<>();
			jwtProcessor.setJWSKeySelector(jwsKeySelector);
			jwtProcessor.setJWSTypeVerifier(this.typeVerifier);
			jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> {
			});
			this.jwtProcessorCustomizer.accept(jwtProcessor);
			return (jwt) -> {
				if (jwt instanceof SignedJWT) {
					return this.jwkSource.apply((SignedJWT) jwt)
						.onErrorMap((e) -> new IllegalStateException("Could not obtain the keys", e))
						.collectList()
						.map((jwks) -> createClaimsSet(jwtProcessor, jwt, new JWKSecurityContext(jwks)));
				}
				throw new BadJwtException("Unsupported algorithm of " + jwt.getHeader().getAlgorithm());
			};
		}

	}

}

View on GitHub (pinned to 96852e8860)