{"record":{"id":"1468f44bbbd17455","repo":"spring-projects/spring-security","slug":"an-error-occurred-while-attempting-to-decode-the-j","errorCode":null,"errorMessage":"An error occurred while attempting to decode the Jwt: Unsupported algorithm of + jwt.getHeader().getAlgorithm()","messagePattern":"An error occurred while attempting to decode the Jwt: 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/NimbusJwtDecoder.java","lineNumber":143,"sourceCode":"\t * @param claimSetConverter the {@link Converter} to use\n\t */\n\tpublic void setClaimSetConverter(Converter<Map<String, Object>, Map<String, Object>> claimSetConverter) {\n\t\tAssert.notNull(claimSetConverter, \"claimSetConverter cannot be null\");\n\t\tthis.claimSetConverter = claimSetConverter;\n\t}\n\n\t/**\n\t * Decode and validate the JWT from its compact claims representation format.\n\t * @param token the JWT value\n\t * @return a validated {@link Jwt}\n\t * @throws JwtException when the token is malformed or otherwise invalid\n\t */\n\t@Override\n\tpublic Jwt decode(String token) throws JwtException {\n\t\tJWT jwt = parse(token);\n\t\tif (jwt instanceof PlainJWT) {\n\t\t\tthis.logger.trace(\"Failed to decode unsigned token\");\n\t\t\tthrow new BadJwtException(\"Unsupported algorithm of \" + jwt.getHeader().getAlgorithm());\n\t\t}\n\t\tJwt createdJwt = createJwt(token, jwt);\n\t\treturn validateJwt(createdJwt);\n\t}\n\n\tprivate JWT parse(String token) {\n\t\ttry {\n\t\t\treturn JWTParser.parse(token);\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tthis.logger.trace(\"Failed to parse token\", ex);\n\t\t\tif (ex instanceof ParseException) {\n\t\t\t\tthrow new BadJwtException(String.format(DECODING_ERROR_MESSAGE_TEMPLATE, \"Malformed token\"), ex);\n\t\t\t}\n\t\t\tthrow new BadJwtException(String.format(DECODING_ERROR_MESSAGE_TEMPLATE, ex.getMessage()), ex);\n\t\t}\n\t}\n","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoder.java#L125-L161","documentation":"NimbusJwtDecoder.decode parses the token and rejects unauthenticated tokens: if the parsed JWT is a PlainJWT (alg=none), it throws BadJwtException 'Unsupported algorithm of none'. Spring Security never accepts unsigned JWTs since they provide no integrity.","triggerScenarios":"Calling NimbusJwtDecoder.decode(token) where JWTParser.parse returns a PlainJWT — i.e. a JWS header with alg=none and no signature segment content.","commonSituations":"Sending raw/unsecured tokens from dev tools or mock identity providers; tokens truncated/corrupted such that they parse as unsecured; confusion with non-JWT opaque tokens passed to a JWT decoder; attackers sending alg=none tokens (this throw is the correct security behavior).","solutions":["Ensure you are sending a properly signed JWT (RS256/ES256 etc.) produced by the authorization server, not an unsigned token.","Verify the client is pointing at the real token endpoint, not a stub returning unsigned tokens.","Check the token has three segments with a real signature; decode the header to inspect the alg value.","If you genuinely need unsigned JWT handling, use Nimbus directly — Spring Security intentionally rejects them."],"exampleFix":"// before (client sending unsigned token)\nString token = base64Header + \".\" + base64Payload + \".\"; // alg=none\n// after\nString token = signedJws.serialize(); // alg=RS256 with signature","handlingStrategy":"validation","validationCode":"String[] parts = token.split(\"\\\\.\");\nif (parts.length != 3) throw new IllegalArgumentException(\"not a JWS\");\nString headerJson = new String(Base64.getUrlDecoder().decode(parts[0]), StandardCharsets.UTF_8);\nif (headerJson.contains(\"\\\"alg\\\":\\\"none\\\"\")) { /* reject: unsigned token */ }","typeGuard":"boolean isSignedJwt(String token) {\n    String[] parts = token.split(\"\\\\.\");\n    return parts.length == 3 && !parts[2].isEmpty();\n}","tryCatchPattern":"try { jwt = jwtDecoder.decode(token); }\ncatch (BadJwtException e) { /* return 401 invalid_token; alg=none is never acceptable */ }","preventionTips":["Never accept alg=none tokens anywhere in your stack","Ensure clients fetch tokens from the real authorization server, not mocks/stubs","Verify tokens have three segments with a non-empty signature before decoding"],"tags":["jwt","unsigned-token","alg-none","security"],"backgroundTag":"jwt-signature-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"}