jwtk/jjwt · error · IllegalArgumentException

The 'none' JWS algorithm cannot be used to sign JWTs.

Error message

The 'none' JWS algorithm cannot be used to sign JWTs.

What it means

The 'none' algorithm means an unsigned JWT and is not permitted as a signing algorithm; calling signWith with it would silently produce an unsecured token while appearing to 'sign' it, so the builder throws IllegalArgumentException.

Source

Thrown at impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtBuilder.java:237

        // Implementation note:  Ordinarily Passwords should not be used to create secure digests because they usually
        // lack the length or entropy necessary for secure cryptographic operations, and are prone to misuse.
        // However, we DO NOT prevent them as arguments here (like the above PublicKey check) because
        // it is conceivable that a custom SecureDigestAlgorithm implementation would allow Password instances
        // so that it might perform its own internal key-derivation logic producing a key that is then used to create a
        // secure hash.
        //
        // Even so, a fallback safety check is that JJWT's only out-of-the-box Password implementation
        // (io.jsonwebtoken.impl.security.PasswordSpec) explicitly forbids calls to password.getEncoded() in all
        // scenarios to avoid potential misuse, so a digest algorithm implementation would explicitly need to avoid
        // this by calling toCharArray() instead.
        //
        // TLDR; the digest algorithm implementation has the final say whether a password instance is valid

        Assert.notNull(alg, "SignatureAlgorithm cannot be null.");
        String id = Assert.hasText(alg.getId(), "SignatureAlgorithm id cannot be null or empty.");
        if (Jwts.SIG.NONE.getId().equalsIgnoreCase(id)) {
            String msg = "The 'none' JWS algorithm cannot be used to sign JWTs.";
            throw new IllegalArgumentException(msg);
        }
        this.key = key;
        //noinspection unchecked
        this.sigAlg = (SecureDigestAlgorithm<Key, ?>) alg;
        this.signFunction = Functions.wrap(request -> sigAlg.digest(request), SignatureException.class, "Unable to compute %s signature.", id);
        return this;
    }

    @SuppressWarnings({"deprecation", "unchecked"}) // TODO: remove method for 1.0
    @Override
    public JwtBuilder signWith(Key key, io.jsonwebtoken.SignatureAlgorithm alg) throws InvalidKeyException {
        Assert.notNull(alg, "SignatureAlgorithm cannot be null.");
        alg.assertValidSigningKey(key); //since 0.10.0 for https://github.com/jwtk/jjwt/issues/334
        return signWith(key, (SecureDigestAlgorithm<? super Key, ?>) Jwts.SIG.get().forKey(alg.getValue()));
    }

    @SuppressWarnings("deprecation") // TODO: remove method for 1.0
    @Override

View on GitHub (pinned to fb71496164)

Solutions

  1. Choose a real algorithm, e.g. signWith(key, Jwts.SIG.HS256) or RS256/ES256 as appropriate for your key type.
  2. If an unsigned token is genuinely intended, use Jwts.builder().unprotected() (or omit signing) instead of signWith with 'none'.
  3. Validate any externally supplied algorithm name against your allow-list before passing it to signWith.
  4. Catch IllegalArgumentException and reject the configuration at startup.

Example fix

// before
builder.signWith(key, Jwts.SIG.NONE);
// after
builder.signWith(key, Jwts.SIG.HS256);
Defensive patterns

Strategy: validation

Validate before calling

if (Jwts.SIG.NONE.getId().equalsIgnoreCase(alg.getId())) throw new IllegalArgumentException("'none' cannot sign");

Try / catch

try { builder.signWith(key, alg); } catch (IllegalArgumentException e) { /* reject 'none' config */ }

Prevention

When it happens

Trigger: JwtBuilder.signWith(key, Jwts.SIG.NONE) (or a SignatureAlgorithm resolving to id 'none').

Common situations: Refactored code after migrating from the deprecated SignatureAlgorithm enum; misconfigured algorithm names coming from properties/env config set to 'none'; code paths that skip signing conditionally but still call signWith.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09). Data as JSON: /api/errors/529c421f5f98c93d. Report an issue: GitHub.