Mensagem de erro
Signed JWT rejected: Invalid signature
Também aparece como
- com.nimbusds.jose.proc.BadJWSException: Signed JWT rejected: Invalid signature
- org.springframework.security.oauth2.jwt.BadJwtException: An error occurred while attempting to decode the Jwt: Signed JWT rejected: Invalid signature
Nimbus JOSE + JWT (Java) — BadJWSException from DefaultJWTProcessor; also surfaced by Spring Security's NimbusJwtDecoder
O que significa
O Nimbus selecionou uma ou mais chaves candidatas para o token (por `kid`, `alg` e tipo de chave), e nenhuma delas verificou a assinatura. A seleção funcionou — caso contrário, você veria “Another algorithm expected, or no matching key(s) found” —, então as chaves em que você confia e a chave que assinou o token são diferentes, ou o token foi modificado. O Spring Security relata a mesma condição por meio do `NimbusJwtDecoder`, com o prefixo “An error occurred while attempting to decode the Jwt:”.
Por que acontece
Mesmo kid, chave diferente
comumIDs de chave como `default`, `rsa1` ou uma data são reutilizados quando uma chave é gerada de novo (por ambiente, por implantação, depois de perder a chave antiga). O verificador encontra uma chave com o `kid` certo que nunca assinou o token.
O servidor de recursos confia nas chaves de outro emissor
comumUm `jwk-set-uri` que aponta para um realm, locatário ou ambiente diferente daquele que emite os tokens.
O segredo HMAC é diferente entre os serviços
ocasionalCom HS256 e um `MACVerifier`, qualquer diferença nos bytes do segredo compartilhado (codificação, quebra de linha no final) torna todas as assinaturas inválidas.
O token foi alterado depois de assinado
ocasionalCabeçalho ou payload recodificados por um proxy, ou um token montado com partes de tokens diferentes.
Como corrigir
- 1.
Configurar o emissor, e não um conjunto de chaves copiado à mão
Com `issuer-uri`, o Spring Security lê o `jwks_uri` do documento de descoberta do emissor e também valida o `iss`.
yaml # Spring Boot resource server: derive the JWK Set from the issuer's discovery document spring: security: oauth2: resourceserver: jwt: issuer-uri: https://issuer.example.com/realms/main - 2.
Comparar impressões digitais, e não só kids
As impressões digitais (thumbprints) da RFC 7638 identificam o material da chave de fato. Se a impressão digital da chave publicada for diferente da impressão digital da chave com que o emissor assina, o `kid` está sendo reutilizado.
java SignedJWT jwt = SignedJWT.parse(token); System.out.println(jwt.getHeader().getKeyID() + " " + jwt.getHeader().getAlgorithm()); JWKSet set = JWKSet.load(new java.net.URI("https://issuer.example.com/.well-known/jwks.json").toURL()); for (JWK key : set.getKeys()) { System.out.println(key.getKeyID() + " " + key.getAlgorithm() + " thumbprint=" + key.computeThumbprint()); }