{"record":{"id":"dbb20b438867ccfd","repo":"jwtk/jjwt","slug":"unsecured-jwss-those-with-an-alg-header-value-of","errorCode":null,"errorMessage":"Unsecured JWSs (those with an alg header value of 'none') are disallowed by default as mandated by https://www.rfc-editor.org/rfc/rfc7518.html#section-3.6. If you wish to allow them to be parsed, call the JwtParserBuilder.unsecured() method, but please read the security considerations covered in that method's JavaDoc before doing so. Header: ${header}","messagePattern":"Unsecured JWSs \\(those with an alg header value of 'none'\\) are disallowed by default as mandated by https://www\\.rfc-editor\\.org/rfc/rfc7518\\.html#section-3\\.6\\. If you wish to allow them to be parsed, call the JwtParserBuilder\\.unsecured\\(\\) method, but please read the security considerations covered in that method's JavaDoc before doing so\\. Header: (.+?)","errorType":"exception","errorClass":"UnsupportedJwtException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java","lineNumber":414,"sourceCode":"        //      Compact Serialization and is the approach taken by CMS [RFC6211].)\n        //\n        final String alg = Strings.clean(header.getAlgorithm());\n        if (!Strings.hasText(alg)) {\n            String msg = tokenized instanceof TokenizedJwe ? MISSING_JWE_ALG_MSG : MISSING_JWS_ALG_MSG;\n            throw new MalformedJwtException(msg);\n        }\n        final boolean unsecured = Jwts.SIG.NONE.getId().equalsIgnoreCase(alg);\n\n        final CharSequence base64UrlDigest = tokenized.getDigest();\n        final boolean hasDigest = Strings.hasText(base64UrlDigest);\n        if (unsecured) {\n            if (tokenized instanceof TokenizedJwe) {\n                throw new MalformedJwtException(JWE_NONE_MSG);\n            }\n            // Unsecured JWTs are disabled by default per the RFC:\n            if (!this.unsecured) {\n                String msg = UNSECURED_DISABLED_MSG_PREFIX + header;\n                throw new UnsupportedJwtException(msg);\n            }\n            if (hasDigest) {\n                throw new MalformedJwtException(JWS_NONE_SIG_MISMATCH_MSG);\n            }\n            if (header.containsKey(DefaultProtectedHeader.CRIT.getId())) {\n                String msg = String.format(CRIT_UNSECURED_MSG, header);\n                throw new MalformedJwtException(msg);\n            }\n        } else if (!hasDigest) { // something other than 'none'.  Must have a digest component:\n            String fmt = tokenized instanceof TokenizedJwe ? MISSING_JWE_DIGEST_MSG_FMT : MISSING_JWS_DIGEST_MSG_FMT;\n            String msg = String.format(fmt, alg);\n            throw new MalformedJwtException(msg);\n        }\n        // ----- crit assertions -----\n        if (header instanceof ProtectedHeader) {\n            Set<String> crit = Collections.nullSafe(((ProtectedHeader) header).getCritical());\n            Set<String> supportedCrit = this.critical;\n            String b64Id = DefaultJwsHeader.B64.getId();","sourceCodeStart":396,"sourceCodeEnd":432,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java#L396-L432","documentation":"Unsecured JWSs (alg='none') are rejected by default as mandated by RFC 7518 Section 3.6. jjwt refuses to parse them unless the application explicitly opts in by calling JwtParserBuilder.unsecured(); when alg is 'none' and the parser is not in unsecured mode, an UnsupportedJwtException carrying the offending header is thrown.","triggerScenarios":"Calling parse(), parseSignedClaims(), or parseSignedContent() on a 3-segment JWS whose header is \"alg\":\"none\" while the parser was built without JwtParserBuilder.unsecured().","commonSituations":"Parsing tokens minted by legacy systems or dev environments that use unsigned JWTs; testing with hand-made none-alg tokens; migrating from libraries that allowed none by default; misconfiguration where the parser was not built with .unsecured().","solutions":["If you intentionally need unsecured tokens, build the parser with Jwts.parser().unsecured() ... (read the method's security JavaDoc first).","Prefer securing tokens: re-issue them signed with a real algorithm (e.g. HS256/RS256) and parse with verifyWith(key).","If unsecured tokens are unexpected, treat this as an upstream issuer problem and reject the token.","For local/dev testing only, enable unsecured parsing in a non-production parser instance."],"exampleFix":"// before\nJws<Claims> jws = Jwts.parser().build().parseSignedClaims(noneToken);\n\n// after (only if truly intended)\nJwtParser parser = Jwts.parser().unsecured().build();\nJwt<Header, Claims> jwt = parser.parse(noneToken);","handlingStrategy":"validation","validationCode":"String headerJson = new String(java.util.Base64.getUrlDecoder().decode(token.split(\"\\\\.\")[0]), java.nio.charset.StandardCharsets.UTF_8);\nboolean unsecured = headerJson.contains(\"alg\\\":\\\"none\\\"\");\nJwtParser p = unsecured ? Jwts.parser().unsecured().build() : Jwts.parser().verifyWith(key).build();","typeGuard":null,"tryCatchPattern":"try { return parser.parse(token); }\ncatch (io.jsonwebtoken.UnsupportedJwtException e) { throw new InvalidTokenException(\"Unsecured JWS rejected\", e); }","preventionTips":["Sign tokens in production; avoid alg=none entirely","If unsecured tokens are required, enable them explicitly with JwtParserBuilder.unsecured() and read its security notes","Keep production and dev parser configurations separate","Reject unsigned tokens at trust boundaries"],"tags":["jwt","jws","unsecured","alg-none","security"],"backgroundTag":"feature-not-enabled","analyzedSha":"fb71496164c71442d08adec4571d9616ed5e1b8d","analyzedAt":"2026-09-09T00:33:09.982Z","contentChangedAt":"2026-09-09T00:33:09.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}