jwtk/jjwt · error · SignatureException

Unsupported signature algorithm '${alg}': ${e.getMessage()}

Error message

Unsupported signature algorithm '${alg}': ${e.getMessage()}

What it means

During parse(), verifySignature() resolves the JWS 'alg' header to a SecureDigestAlgorithm via the configured algorithm registry. If the header names an algorithm not registered/supported (or disabled by policy), the lookup throws UnsupportedJwtException, which is wrapped into a SignatureException with this message for backwards compatibility.

Source

Thrown at impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java:280

        }
    }

    private static boolean hasContentType(Header header) {
        return header != null && Strings.hasText(header.getContentType());
    }

    private byte[] verifySignature(final TokenizedJwt tokenized, final JwsHeader jwsHeader, final String alg,
                                   @SuppressWarnings("deprecation") SigningKeyResolver resolver, Claims claims, Payload payload) {

        Assert.notNull(resolver, "SigningKeyResolver instance cannot be null.");

        SecureDigestAlgorithm<?, Key> algorithm;
        try {
            algorithm = (SecureDigestAlgorithm<?, Key>) sigAlgs.apply(jwsHeader);
        } catch (UnsupportedJwtException e) {
            //For backwards compatibility.  TODO: remove this try/catch block for 1.0 and let UnsupportedJwtException propagate
            String msg = "Unsupported signature algorithm '" + alg + "': " + e.getMessage();
            throw new SignatureException(msg, e);
        }
        Assert.stateNotNull(algorithm, "JWS Signature Algorithm cannot be null.");

        //digitally signed, let's assert the signature:
        Key key;
        if (claims != null) {
            key = resolver.resolveSigningKey(jwsHeader, claims);
        } else {
            key = resolver.resolveSigningKey(jwsHeader, payload.getBytes());
        }
        if (key == null) {
            String msg = "Cannot verify JWS signature: unable to locate signature verification key for JWS with header: " + jwsHeader;
            throw new UnsupportedJwtException(msg);
        }
        Provider provider = ProviderKey.getProvider(key, this.provider); // extract if necessary
        key = ProviderKey.getKey(key); // unwrap if necessary, MUST be called after ProviderKey.getProvider
        Assert.stateNotNull(key, "ProviderKey cannot be null."); //ProviderKey impl doesn't allow null
        if (key instanceof PrivateKey) {

View on GitHub (pinned to fb71496164)

Solutions

  1. Enable the needed algorithm in the parser via .sig().add(...) (or use Jwts.SIG defaults) or re-mint tokens with a supported algorithm
  2. Check the 'alg' header of the failing token and ensure it matches what your verifyKey/verifyWith expects
  3. If you intentionally reject the alg, catch SignatureException/UnsupportedJwtException and reject the token rather than enabling weak algorithms

Example fix

// before
Jws<Claims> jws = Jwts.parser().verifyWith(key).build().parseSignedClaims(token); // alg not in allowed set
// after
Jws<Claims> jws = Jwts.parser()
    .sig().add(Jwts.SIG.HS256).and()
    .verifyWith(key)
    .build()
    .parseSignedClaims(token);
Defensive patterns

Strategy: try-catch

Try / catch

try {
    return parser.parseSignedClaims(token);
} catch (SignatureException e) {
    if (e.getMessage().startsWith("Unsupported signature algorithm")) {
        log.warn("Token uses unregistered alg");
    }
    throw new UnauthorizedException(e);
}

Prevention

When it happens

Trigger: Parsing a JWS whose 'alg' header names an algorithm not enabled in the parser (e.g. 'none' where signing required, or an algorithm removed/disabled via sig().add/remove, or a non-standard alg string like HS512 modified or typo'd).

Common situations: Token minted by another system using an algorithm your parser disabled; downgrade attempts; upgrading jjwt versions where legacy algorithms were excluded from defaults; attacker-supplied alg headers.

Related errors


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