{"record":{"id":"cbbc1fc13e5e0bbe","repo":"jwtk/jjwt","slug":"unexpected-unsecured-claims-jwt","errorCode":null,"errorMessage":"Unexpected unsecured Claims JWT.","messagePattern":"Unexpected unsecured Claims JWT\\.","errorType":"exception","errorClass":"UnsupportedJwtException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/io/jsonwebtoken/SupportedJwtVisitor.java","lineNumber":89,"sourceCode":"     * @throws UnsupportedJwtException by default, expecting the subclass implementation to override as necessary.\n     */\n    public T onUnsecuredContent(Jwt<Header, byte[]> jwt) throws UnsupportedJwtException {\n        throw new UnsupportedJwtException(\"Unexpected unsecured content JWT.\");\n    }\n\n    /**\n     * Handles an encountered unsecured Claims JWT - one that is not cryptographically signed nor\n     * encrypted, and has a {@link Claims} payload.\n     *\n     * <p>The default implementation immediately throws an {@link UnsupportedJwtException}; it is expected that\n     * subclasses will override this method if the application needs to support this type of JWT.</p>\n     *\n     * @param jwt the parsed unsecured content JWT\n     * @return any object to be used after inspecting the JWT, or {@code null} if no return value is necessary.\n     * @throws UnsupportedJwtException by default, expecting the subclass implementation to override as necessary.\n     */\n    public T onUnsecuredClaims(Jwt<Header, Claims> jwt) {\n        throw new UnsupportedJwtException(\"Unexpected unsecured Claims JWT.\");\n    }\n\n    /**\n     * Handles an encountered JSON Web Token (aka 'JWS') message that has been cryptographically verified/authenticated\n     * by delegating to either {@link #onVerifiedContent(Jws)} or {@link #onVerifiedClaims(Jws)} depending on the payload\n     * type.\n     *\n     * @param jws the parsed verified/authenticated JWS.\n     * @return the value returned by either {@link #onVerifiedContent(Jws)} or {@link #onVerifiedClaims(Jws)}\n     * depending on the payload type.\n     * @throws UnsupportedJwtException if the payload is neither a {@code byte[]} nor {@code Claims}, or either\n     *                                 delegate method throws the same.\n     */\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public T visit(Jws<?> jws) {\n        Assert.notNull(jws, \"JWS cannot be null.\");\n        Object payload = jws.getPayload();","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/api/src/main/java/io/jsonwebtoken/SupportedJwtVisitor.java#L71-L107","documentation":"SupportedJwtVisitor.onUnsecuredClaims is a default visitor callback invoked when the parser encounters an unsecured JWT (alg=none) whose payload is a Claims JSON object. The base class intentionally throws UnsupportedJwtException because plain, unsigned JWTs are unsafe (their contents can be modified by anyone without detection). Applications must override this method to explicitly opt in to handling unsecured Claims JWTs.","triggerScenarios":"Parsing a compact 'header.payload.' token whose header declares alg=none (or an unsecured JWS) with a Claims payload, using a JwtParser whose visitor does not override onUnsecuredClaims. E.g. Jwts.parser().build().parse(...)/parseClaimsJwt on a token created with Jwts.builder()...compact() without signing (or signWith with no key / alg none).","commonSituations":"Migrating code that previously accepted unsigned tokens; tokens received from a legacy or third-party issuer that emits alg=none tokens; a developer forgot to configure a signing key so the produced token was unsecured; security-hardened parsers rejecting unsigned tokens by design.","solutions":["Sign the JWT on the issuing side (e.g. jwsBuilder via Jwts.builder().signWith(key)) and verify it on parse, eliminating unsecured tokens entirely.","If unsecured Claims JWTs are genuinely expected, subclass SupportedJwtVisitor and override onUnsecuredClaims to return a value instead of throwing.","If unsecured tokens should never appear, treat the exception as a security signal: reject the token and log/audit the source.","Use parseClaimsJwt only for tokens you know are unsecured; otherwise use parseClaimsJws with the correct verification key."],"exampleFix":"// before\nT result = visitor.onUnsecuredClaims(jwt); // throws UnsupportedJwtException\n// after\npublic class MyVisitor extends SupportedJwtVisitor<MyType> {\n    @Override\n    public MyType onUnsecuredClaims(Jwt<Header, Claims> jwt) {\n        if (isTrustedUnsecuredIssuer(jwt.getHeader())) {\n            return processClaims(jwt.getBody());\n        }\n        throw new UnsupportedJwtException(\"Unsecured JWTs not allowed\");\n    }\n}","handlingStrategy":"try-catch","validationCode":"// Inspect the token before parsing: an unsecured JWT has a trailing dot and alg=none header\nString[] parts = compactJwt.split(\"\\\\.\", -1);\nboolean unsecured = parts.length == 3 && parts[2].isEmpty();\nif (unsecured && !allowUnsecuredTokens) {\n    throw new IllegalArgumentException(\"Unsecured JWTs are not accepted\");\n}","typeGuard":"boolean isUnsecuredJwt(String token) {\n    String[] p = token.split(\"\\\\.\", -1);\n    return p.length == 3 && p[2].isEmpty() && new String(Base64.getUrlDecoder().decode(p[0])).contains(\"\\\"none\\\"\");\n}","tryCatchPattern":"try {\n    result = Jwts.parser().build().parseClaimsJwt(token);\n} catch (UnsupportedJwtException e) {\n    log.warn(\"Rejected unsecured Claims JWT\", e);\n    throw new SecurityException(\"Unsecured JWTs are not allowed here\", e);\n}","preventionTips":["Always sign issued JWTs; treat alg=none tokens as untrusted input","Override every on* callback of SupportedJwtVisitor you can receive, or use parseClaimsJwt/parseClaimsJws deliberately","Reject unsecured tokens at your auth filter before deep parsing","Pin the expected algorithm in the parser configuration (require alg) to fail fast"],"tags":["java","jwt","jjwt","unsupported-jwt","unsecured-token"],"backgroundTag":"unsupported-operation","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"}