Um (JSON Web Key Set, um conjunto de chaves em JSON) só tem utilidade no momento em que você verifica um token. A verificação em si é um pequeno pipeline, e acertar cada passo exatamente é o que separa um verificador seguro de um que dá para burlar.

A sequência

Primeiro, leia o header (o cabeçalho) do token, o primeiro segmento dele, que é um JSON codificado em base64url. O header diz duas coisas de que você precisa: o alg com que o token diz ter sido assinado e o kid da chave que o assinou.

Segundo, busque o JWKS do provedor (guardado em cache e atualizado quando aparece um kid que não está nele) e encontre a chave cujo kid bate com o do header. Se nenhuma chave bater, pare: não há chave com que verificar. Se exatamente uma bater, essa é a sua chave.

Terceiro, confirme o algoritmo. O alg da chave, ou o tipo dela, tem de ser um que a sua aplicação espera. Defina de antemão quais algoritmos são aceitos, em vez de confiar no que o token pedir.

Quarto, faça a verificação da assinatura com essa chave e esse algoritmo sobre o header e o payload (a carga útil do token). Só se ela passar é que você valida as claims (issuer, audience, expiração).

O explicador de JWKS faz os dois primeiros passos para você: cole um JWKS e um , e ele lê o header e informa qual chave o kid seleciona, ou que nenhuma é selecionada.

As armadilhas que importam

Três erros clássicos transformam esse pipeline numa vulnerabilidade.

O primeiro é a confusão de algoritmo (algorithm confusion). Se um verificador confia cegamente no alg do header, o atacante pode trocá-lo. O caso famoso troca um token RS256 (assimétrico) por HS256 (simétrico) e o assina com a chave pública do provedor como se ela fosse um segredo ; um verificador que não fixa o algoritmo aceita esse token. Decida sempre o algoritmo aceito a partir da chave, e não a partir do header, que é controlado pelo atacante.

O segundo é aceitar alg igual a none. A especificação do (JSON Web Signature) define um algoritmo none, sem proteção, com a assinatura vazia. Um verificador nunca deve aceitá-lo para tokens que deveriam estar assinados.

O terceiro é selecionar pelo campo errado. Se o header não tem kid, algumas bibliotecas passam a procurar a chave pelo alg, o que é frágil e pode pegar a chave errada. Um provedor bem configurado sempre define um kid; o explicador sinaliza quando ele falta e mostra o fallback frágil por alg quando precisa usá-lo.

Veja de ponta a ponta

Para acompanhar o caminho que vai do header até a chave correspondente, use o explicador de JWKS. Para o documento que guarda essas chaves, veja JWKS e rotação de chaves; para o que compõe cada chave, veja tipos de chave JWK.