Pular para o conteúdo
ecdsa.com
JJWT (Java)Java

Mensagem de erro

JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.

Também aparece como

  • io.jsonwebtoken.security.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.

JJWT (Java) — io.jsonwebtoken.security.SignatureException from JwtParser.parseSignedClaims

O que significa

O JJWT recalculou (HMAC) ou verificou (RSA, ECDSA, EdDSA) a assinatura sobre o cabeçalho e o payload do token com a chave que você configurou, e o resultado não correspondeu ao segmento de assinatura do token. O token foi analisado sem problemas e o algoritmo combinava com a chave; a chave e o token simplesmente não pertencem um ao outro, ou o token mudou depois de ser assinado.

Por que acontece

Como corrigir

  1. 1.

    Resolver chaves pelo kid com um localizador de chaves

    O JJWT 0.12+ oferece suporte a `keyLocator`, que recebe o cabeçalho e retorna a chave certa. Combine-o com um JWKS que você atualiza a cada rotação.

    java
    import io.jsonwebtoken.*;
    import java.security.Key;
    
    // Pick the verification key by the token's kid instead of a single static key.
    Locator<Key> keys = new LocatorAdapter<>() {
      @Override
      protected Key locate(JwsHeader header) {
        Key key = publicKeysByKid.get(header.getKeyId()); // refreshed from the issuer's JWKS
        if (key == null) throw new UnsupportedJwtException("unknown kid " + header.getKeyId());
        return key;
      }
    };
    Jws<Claims> jws = Jwts.parser().keyLocator(keys).requireIssuer("https://issuer.example.com/").build().parseSignedClaims(token);
  2. 2.

    Usar os mesmos bytes de chave HMAC em todos os lados

    Decida se o segredo configurado é texto ou base64 e derive a chave da mesma forma em todos os lados. A calculadora de HMAC mostra o MAC nas duas interpretações.

    java
    // Both sides must derive the same key bytes. If the secret is stored base64-encoded, decode it.
    javax.crypto.SecretKey key = io.jsonwebtoken.security.Keys.hmacShaKeyFor(
        java.util.Base64.getDecoder().decode(System.getenv("JWT_SECRET_B64")));

Erros relacionados

Ver toda a base de erros de assinatura