Guias JWT

Rotação de Chaves JWT e JWKS sem Quebrar a Verificação

Entenda como coordenar kid, JWKS, cache, overlap entre chave antiga e nova, vida do token e revogação durante rotação de chaves JWT.

Por JWTDecoder.toolsÚltima verificação em 2026-09-12

Voz editorial: a primeira pessoa descreve o fluxo de trabalho documentado do JWTDecoder.tools; JWTDecoder.tools é o editor e autor organizacional.

KEY A → A + B → KEY B
KEY A → A + B → KEY B · TTL · cache · exp

Quando a verificação começa a falhar perto de uma troca de chave, trato o caso como problema de ciclo de vida da chave, não apenas como “invalid signature”. O token pode estar correto e o verifier também; a falha pode estar no momento em que a chave antiga sai, a nova entra ou o cache JWKS deixa de acompanhar a mudança.

A pergunta que tento responder é:

Este token foi assinado com uma chave que o verifier ainda consegue encontrar e confiar durante toda a janela em que o token pode ser aceito?

Com token e JWKS em mãos, começo no Validador JWKS.

1. Leio kid, iss, alg e exp

Um cabeçalho pode conter:

{
  "alg": "RS256",
  "kid": "signing-key-2026-09"
}

E o payload:

{
  "iss": "https://login.example.com/",
  "exp": 1789203600
}

Quero saber:

  • qual issuer é responsável pela chave;
  • qual kid o token usa para seleção;
  • qual algoritmo é esperado;
  • por quanto tempo esse token ainda pode precisar ser verificado.

A RFC 7517 descreve kid como mecanismo para escolher entre chaves em um JWK Set, inclusive durante rollover.

2. Comparo o JWKS atual com o kid

Durante uma rotação planejada, posso esperar overlap:

{
  "keys": [
    {"kid":"signing-key-2026-06","kty":"RSA","alg":"RS256","use":"sig"},
    {"kid":"signing-key-2026-09","kty":"RSA","alg":"RS256","use":"sig"}
  ]
}

Se um token antigo ainda válido usa kid=signing-key-2026-06, remover a chave pública antiga cedo demais pode quebrar sua verificação mesmo com exp no futuro.

O guia de JWT kid ajuda quando o sintoma é apenas kid not found.

3. Separo rotação planejada de revogação de emergência

Não aplico a mesma política em todos os casos.

Em rotação planejada, normalmente quero publicar a nova chave, começar a assinar com ela e manter a chave pública antiga disponível pelo tempo necessário para tokens já emitidos.

Em comprometimento de chave, manter a chave antiga confiável até todos os tokens expirarem pode ser exatamente o que não quero. A política de incidente pode exigir rejeitar imediatamente tokens assinados por uma chave comprometida.

Portanto, não transformo “manter overlap” em regra absoluta. O motivo da troca importa.

4. Verifico cache de JWKS

É comum o issuer publicar a chave nova corretamente e a aplicação continuar usando um conjunto antigo em memória.

Investigo:

  • TTL do cache JWKS;
  • refresh periódico;
  • refresh controlado ao encontrar kid desconhecido;
  • cache em gateway, framework e aplicação;
  • instâncias com estados diferentes;
  • CDN/proxy servindo metadata antiga;
  • fallback que fixa uma chave velha depois de erro de rede.

Um kid desconhecido pode disparar refresh da origem JWKS já confiável, com rate limiting e controles normais de rede.

O que evito é deixar dados arbitrários do token escolherem uma URL nova para baixar chaves.

5. Confirmo que a chave nova pertence ao mesmo issuer confiável

A sequência que quero preservar é:

issuer esperado
      ↓
metadata/configuração confiável
      ↓
JWKS confiável
      ↓
kid compatível
      ↓
JWK compatível
      ↓
verificação da assinatura

Se uma implantação pega por engano o JWKS de staging e encontra um kid parecido, não considero isso uma rotação bem-sucedida.

O guia de validação de issuer cobre essa ligação.

6. Confiro metadados da JWK

Mesmo com kid correto, verifico:

{
  "kty": "RSA",
  "kid": "signing-key-2026-09",
  "use": "sig",
  "alg": "RS256"
}

kty, alg, use e key_ops, quando presentes, precisam ser compatíveis com a operação de assinatura. A allowlist de algoritmo pertence à aplicação; não vem do token.

7. Comparo o tempo da rotação com a vida do token

Imagine access tokens de 60 minutos:

11:59 token assinado com chave antiga
12:00 chave nova começa a assinar
12:01 chave pública antiga removida
12:30 token antigo ainda tem 29 minutos de exp

Em uma rotação planejada, isso cria uma lacuna. O período de publicação simultânea das chaves precisa refletir o tempo máximo em que tokens antigos continuam aceitáveis, mais os buffers operacionais definidos pelo sistema.

Não deduzo esse período da RFC. Ele depende da política do provedor e da aplicação.

8. Comparo tokens antes e depois da rotação

Quando possível, pego:

  • um token emitido pouco antes;
  • um token emitido pouco depois.

Comparo kid, issuer, exp e resultado da assinatura contra o JWKS atual.

Isso separa rapidamente:

  • chave antiga removida cedo;
  • chave nova ainda não publicada;
  • cache antigo;
  • issuer/ambiente errado;
  • falha geral de assinatura sem relação com rotação.

9. Não desativo assinatura durante rollout

Um workaround perigoso seria:

A chave nova ainda não chegou, então vamos ignorar assinatura por alguns minutos.

Não faço isso. Corrijo distribuição de chaves, cache ou ordem do rollout.

Um padrão saudável de rotação planejada é:

1. Publicar nova chave pública no JWKS
2. Manter a chave pública antiga
3. Começar a assinar novos tokens com a nova chave/kid
4. Verificadores aceitam as duas chaves públicas
5. Esperar a janela de tokens antigos terminar
6. Remover a chave antiga quando a política permitir

Meu checklist de rotação JWT

  1. Decodifico iss, alg, kid e exp.
  2. Confirmo o issuer esperado.
  3. Inspeciono o JWKS confiável atual.
  4. Procuro o kid do token.
  5. Confiro kty, alg, use e key_ops.
  6. Verifico a assinatura no Validador JWKS.
  7. Inspeciono idade e política de refresh do cache.
  8. Comparo vida de token com disponibilidade da chave antiga.
  9. Distingo rollover planejado de revogação de emergência.
  10. Mantenho verificação de assinatura ativa durante toda a correção.

Para mim, rotação de chave JWT é coordenação entre publicação de chave pública, seleção por kid, cache, vida do token e confiança no issuer — não apenas trocar uma chave privada.

Fontes e referências

Guias relacionados