Guias JWT

JWK vs JWKS: Diferença na Verificação de JWT

Entenda a diferença entre uma JWK e um JWKS, como kid seleciona a chave e quando usar uma chave individual, um key set ou jwks_uri confiável.

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.

Diagrama de issuer confiável, JWKS, kid e JWK
Um issuer confiável publica JWKS; kid seleciona a JWK usada para verificar a assinatura.

Quando encontro JWK e JWKS na documentação de JWT, uso um modelo simples:

JWK é uma chave criptográfica representada em JSON. JWKS é um objeto que contém um conjunto de JWKs.

A diferença parece pequena até entrar em cena kid, rotação de chaves, vários algoritmos ou um jwks_uri publicado pelo issuer.

Se já tenho um JWT e um conjunto de chaves, uso o Validador JWKS porque ele reproduz o fluxo que quero em uma aplicação: ler kid, selecionar uma JWK compatível dentro de um conjunto confiável e verificar a assinatura.

O que é JWK

A RFC 7517 define JSON Web Key (JWK) como uma representação JSON de uma chave criptográfica.

Uma chave pública RSA pode parecer:

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

Ao ler esse objeto, observo:

  • kty — tipo da chave;
  • kid — identificador;
  • use — uso de alto nível, como assinatura;
  • key_ops — operações permitidas, quando informado;
  • alg — algoritmo associado, quando informado;
  • material de chave como n/e para RSA ou crv/x/y para EC.

Uma JWK bem formada não é automaticamente confiável. Preciso saber de onde ela veio e para qual issuer minha aplicação a aceita.

O que é JWKS

A RFC 7517 define um JWK Set como um objeto com um array keys contendo JWKs:

{
  "keys": [
    {
      "kty": "RSA",
      "kid": "key-old",
      "use": "sig",
      "alg": "RS256",
      "n": "...",
      "e": "AQAB"
    },
    {
      "kty": "RSA",
      "kid": "key-new",
      "use": "sig",
      "alg": "RS256",
      "n": "...",
      "e": "AQAB"
    }
  ]
}

Na prática de desenvolvimento, esse conjunto é chamado de JWKS — JSON Web Key Set.

Minha regra de memória é:

JWK  = uma chave
JWKS = um conjunto de chaves

Por que encontro JWKS com tanta frequência

Sistemas reais precisam lidar com:

  • rotação de chaves;
  • mais de uma chave ativa;
  • tipos de chave diferentes;
  • algoritmos diferentes;
  • overlap entre chave antiga e nova.

JWKS permite publicar várias chaves públicas ao mesmo tempo.

Por isso um JWT pode trazer:

{
  "alg": "RS256",
  "kid": "key-new"
}

Uso kid para selecionar uma candidata dentro do conjunto confiável.

Como kid participa da seleção

Meu fluxo é:

JWT header kid
      ↓
JWKS do issuer confiável
      ↓
JWK com kid correspondente
      ↓
validar kty / alg / use / key_ops
      ↓
importar chave
      ↓
verificar assinatura

Não paro no match de kid. O guia de JWT kid mostra o que faço quando o identificador está ausente, duplicado, não existe ou ficou desatualizado após rotação.

Quando uso uma JWK individual

Uma única JWK é suficiente quando:

  • já selecionei a chave exata de um conjunto confiável;
  • uma configuração armazena uma chave pública em JSON;
  • quero importar uma chave específica na Web Crypto API ou em uma biblioteca JOSE;
  • estou depurando parâmetros de uma chave RSA ou EC.

O Web Crypto pode importar uma JWK pública compatível diretamente:

const publicKey = await crypto.subtle.importKey(
  "jwk",
  jwk,
  {
    name: "RSASSA-PKCS1-v1_5",
    hash: "SHA-256"
  },
  false,
  ["verify"]
);

O ponto de segurança é anterior à importação: a aplicação já precisa ter selecionado essa JWK a partir de uma fonte confiável.

Quando mantenho o JWKS completo

Guardo o conjunto enquanto ainda preciso resolver seleção de chave, por exemplo:

  • issuer que faz rotação;
  • tokens com kid diferentes;
  • refresh quando aparece um kid desconhecido;
  • período de overlap entre chaves antigas e novas;
  • resource server que valida tokens continuamente.

O guia de rotação de chaves JWT mostra por que duas JWKs podem precisar coexistir por algum tempo.

O que é jwks_uri

A RFC 8414 define jwks_uri em metadata de authorization server como a URL do JWK Set.

Exemplo:

{
  "issuer": "https://login.example.com/",
  "jwks_uri": "https://login.example.com/.well-known/jwks.json"
}

Eu uso essa relação como cadeia de confiança:

issuer configurado/confiável
        ↓
metadata confiável
        ↓
jwks_uri
        ↓
JWKS
        ↓
JWK selecionada por kid

Não inverto a lógica dizendo “o token trouxe uma URL, então vou confiar nas chaves de lá”.

JWK versus PEM

JWK é uma representação JSON de material de chave. PEM é uma representação textual muito usada para estruturas ASN.1 de chaves e certificados.

A mesma chave pública RSA pode frequentemente aparecer como:

-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----

ou como JWK com kty, n e e.

Escolho o formato de acordo com a integração. Muitos identity providers publicam JWKS; várias bibliotecas de servidor aceitam PEM; Web Crypto lida bem com import de JWK.

O formato muda. A decisão de confiança não.

Por que use, key_ops e alg importam

Quando presentes, esses metadados ajudam a impedir seleção sem sentido.

Para verificação posso encontrar:

{
  "use": "sig",
  "key_ops": ["verify"],
  "alg": "RS256"
}

Se uma chave declara use: "enc", não a escolho para verificar assinatura só porque o kid coincide.

O modelo durante rotação

Antes:

JWKS
└── JWK A

Durante overlap:

JWKS
├── JWK A (antiga)
└── JWK B (nova)

Depois:

JWKS
└── JWK B

kid ajuda o verifier a escolher a JWK correta enquanto tokens de gerações diferentes coexistem.

Meu checklist antes de confiar em uma JWK

  1. Confirmo o issuer que a aplicação confia.
  2. Obtenho o JWKS da origem configurada/derivada de metadata confiável.
  3. Leio kid como dica de seleção.
  4. Encontro a JWK candidata.
  5. Confiro kty, alg, use e key_ops quando presentes.
  6. Importo com o algoritmo esperado pela aplicação.
  7. Verifico a assinatura.
  8. Depois valido issuer, audience, expiração e tipo do token.

A forma mais curta de lembrar é: JWK é a chave; JWKS é o chaveiro; kid ajuda a escolher qual chave do chaveiro tentar. E esse chaveiro precisa vir de um issuer que eu já confio.

Fontes e referências

Guias relacionados