{"record":{"id":"158cb2f7a76f2aff","repo":"spring-projects/spring-security","slug":"unsupported-algorithm-of-jwt-getheader-getalgo","errorCode":null,"errorMessage":"Unsupported algorithm of + jwt.getHeader().getAlgorithm()","messagePattern":"Unsupported algorithm of \\+ jwt\\.getHeader\\(\\)\\.getAlgorithm\\(\\)","errorType":"exception","errorClass":"BadJwtException","httpStatus":null,"severity":"error","filePath":"oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoder.java","lineNumber":943,"sourceCode":"\n\t\tConverter<JWT, Mono<JWTClaimsSet>> processor() {\n\t\t\tJWKSecurityContextJWKSet jwkSource = new JWKSecurityContextJWKSet();\n\t\t\tJWSKeySelector<JWKSecurityContext> jwsKeySelector = new JWSVerificationKeySelector<>(this.jwsAlgorithm,\n\t\t\t\t\tjwkSource);\n\t\t\tDefaultJWTProcessor<JWKSecurityContext> jwtProcessor = new DefaultJWTProcessor<>();\n\t\t\tjwtProcessor.setJWSKeySelector(jwsKeySelector);\n\t\t\tjwtProcessor.setJWSTypeVerifier(this.typeVerifier);\n\t\t\tjwtProcessor.setJWTClaimsSetVerifier((claims, context) -> {\n\t\t\t});\n\t\t\tthis.jwtProcessorCustomizer.accept(jwtProcessor);\n\t\t\treturn (jwt) -> {\n\t\t\t\tif (jwt instanceof SignedJWT) {\n\t\t\t\t\treturn this.jwkSource.apply((SignedJWT) jwt)\n\t\t\t\t\t\t.onErrorMap((e) -> new IllegalStateException(\"Could not obtain the keys\", e))\n\t\t\t\t\t\t.collectList()\n\t\t\t\t\t\t.map((jwks) -> createClaimsSet(jwtProcessor, jwt, new JWKSecurityContext(jwks)));\n\t\t\t\t}\n\t\t\t\tthrow new BadJwtException(\"Unsupported algorithm of \" + jwt.getHeader().getAlgorithm());\n\t\t\t};\n\t\t}\n\n\t}\n\n}\n","sourceCodeStart":925,"sourceCodeEnd":950,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoder.java#L925-L950","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the token header alg and ensure the decoder's jwsAlgorithms includes it","Ensure the issuer produces SignedJWTs (signed, not encrypted or unsecured tokens)","Use NimbusJwtDecoder/NimbusReactiveJwtDecoder withJweDecoder support if encrypted tokens are the real input","Regenerate a valid signed test token from the Authorization Server"],"exampleFix":"// before\nJWSAlgorithm expected = JWSAlgorithm.HS256; // token actually uses ES256\n// after\nJWSAlgorithm expected = JWSAlgorithm.ES256;\nNimbusReactiveJwtDecoder decoder = NimbusReactiveJwtDecoder.withJwkSource(jwkSource)\n    .jwsAlgorithm(SignatureAlgorithm.ES256).build();","handlingStrategy":"try-catch","validationCode":"// confirm token is a SignedJWT with expected alg before calling the decoder\nString[] parts = jwt.split(\"\\\\.\");\nif (parts.length != 3) throw new IllegalArgumentException(\"Not a JWS (3 segments expected)\");","typeGuard":null,"tryCatchPattern":"try {\n    Jwt jwt = decoder.decode(token);\n} catch (BadJwtException e) {\n    log.warn(\"Token not a supported signed JWT: {}\", e.getMessage());\n    throw new UnauthorizedException(\"Unsupported token type/algorithm\");\n}","preventionTips":["Only feed signed JWS tokens to jwkSource-based decoders","Align jwsAlgorithm() with what the issuer actually signs with","Never test with alg=none or hand-crafted tokens against production decoders"],"tags":["jwt","oauth2","algorithm-validation","reactive"],"backgroundTag":"jwt-verification-failed","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}