O que há dentro de um JWT e por que decodificar não é verificar
Um JSON Web Token (JWT) é um texto formado por três partes unidas por pontos: um cabeçalho, um payload e uma assinatura. As duas primeiras apenas são codificadas, não criptografadas, então qualquer pessoa que tenha o token pode lê-las. A assinatura permite que um servidor confirme que uma parte confiável emitiu o token e que ninguém o alterou. Decodificar um token mostra o que ele diz. Só verificá-lo mostra se você deve acreditar nele.
Decodificador JWTToken expirou, ou ainda é válido?Use de graçaAs três partes
Um token tem a forma header.payload.signature. A primeira parte do conhecido token de exemplo do jwt.io é:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Cada uma das duas primeiras partes é um JSON convertido para base64url, um formato de texto seguro para URLs. A primeira parte decodifica para:
{"alg":"HS256","typ":"JWT"}
O payload do mesmo exemplo decodifica para:
{"sub":"1234567890","name":"John Doe","iat":1516239022}
O payload guarda as claims, que são afirmações sobre o usuário ou a sessão. A assinatura é calculada a partir das duas primeiras partes e de uma chave, então basta mudar um caractere para ela deixar de bater. Como o base64url pode ser revertido sem chave, nunca coloque senha, chave privada ou dado pessoal em um payload.
Claims registradas
A RFC 7519, o padrão dos JWTs, reserva alguns nomes curtos de claims:
iss(emissor): quem criou o token.sub(assunto): a quem o token se refere, geralmente um ID de usuário.aud(audiência): o serviço para o qual o token se destina.exp(tempo de expiração): o momento após o qual o token é inválido.nbf(não antes de): o instante mais cedo em que o token é válido.iat(emitido em): quando o token foi criado.
Os horários são segundos desde 1º de janeiro de 1970 UTC, chamados de tempo Unix. O exemplo não tem exp, então, pelo padrão, ele nunca expira. Um token real deve ter um. Outros nomes, como role ou email, pertencem à aplicação.
Decodificar não é verificar
Decodificar divide o token nos pontos, reverte o base64url e lê o JSON. Isso mostra o que o token afirma, e faz o mesmo com um token forjado, porque qualquer um pode escrever quaisquer claims com qualquer assinatura.
Verificar recalcula a assinatura com a chave correta e confere se ela bate. Também confere se exp e nbf delimitam o horário atual, e se iss e aud são os valores que o serviço espera. Um app que lê uma claim role sem verificar confia em quem escreveu o token. Esse é um erro comum.
HS256, RS256 e ES256
O valor de alg indica o método. Três são comuns:
- HS256 é HMAC com SHA-256. Um único segredo compartilhado assina e verifica, então ele precisa ficar no servidor que emite os tokens.
- RS256 é uma assinatura RSA com SHA-256. O emissor assina com uma chave privada, e qualquer um com a chave pública pode verificar. Outros serviços conseguem checar tokens sem conseguir criá-los.
- ES256 é uma assinatura ECDSA com a curva P-256 e SHA-256. Funciona como o RS256, com chaves e assinaturas menores.
Use HS256 quando um único serviço emite e verifica seus tokens. Use RS256 ou ES256 quando outros serviços precisam verificar tokens que não emitiram.
Problemas que vêm de confiar no cabeçalho
O cabeçalho é escrito por quem envia o token, então quem verifica não deve deixar que ele escolha as regras.
alg: none. Um token sem assinatura pode declarar"alg":"none". Algumas bibliotecas já aceitaram esses tokens e pularam a verificação. Defina os algoritmos permitidos no seu próprio código, nunca os tire do token.- Confusão de algoritmo. Um servidor espera RS256 e tem uma chave pública. Um atacante envia um token HS256 assinado usando essa chave pública como segredo HMAC. Um verificador que aceita qualquer algoritmo que o cabeçalho indicar, aceita. Vincule cada chave a exatamente um algoritmo.
- Segredos fracos. O atacante tem o cabeçalho, o payload e a assinatura, então pode testar segredos candidatos offline. Um segredo curto ou uma palavra comum cai rápido nessa lista. A RFC 7518 diz que uma chave HS256 deve ter pelo menos 256 bits e ser aleatória.
Colar um token de produção em um site
Um token válido e não expirado funciona para quem o possui, até expirar. Trate-o como uma senha. Antes de colar um em um site, descubra se o site o envia a um servidor. Uma ferramenta que roda inteiramente na aba do navegador não precisa disso. Você pode verificar qualquer página observando as requisições de rede nas ferramentas de desenvolvedor do navegador.
Tokens geralmente não podem ser revogados antes de expirar, a menos que o servidor mantenha uma lista. Se um token ativo vazar, peça ao serviço para revogar a sessão ou rotacionar as chaves. Use um token de ambiente de teste para depurar sempre que possível. O decodificador JWT lê as três partes na aba do seu navegador, e nada do que você colar é enviado para lugar nenhum.
Webhooks: a mesma ideia com um segredo compartilhado
A maioria dos provedores de webhook envia, em um cabeçalho, um HMAC do corpo da requisição, calculado com um segredo que você compartilha com eles. Seu receptor calcula o mesmo HMAC e compara os dois. As falhas comuns são pequenas. O JSON é reformatado antes do hash, então os bytes mudam. O segredo de teste é usado com tráfego real. Ou as assinaturas são comparadas com igualdade de string comum, o que pode vazar informação de tempo. Use uma comparação de tempo constante.
O testador de assinatura de webhook calcula a assinatura a partir do segredo e do corpo que você colar, para GitHub, Stripe, Slack, Shopify ou qualquer esquema HMAC, para você ver se os dois valores batem.
Respostas rápidas
Um JWT é criptografado?
Não. Um JWT padrão é assinado, e qualquer pessoa pode ler o cabeçalho e o payload. Só a assinatura o protege contra alterações.
O que acontece se eu editar o payload?
A assinatura deixa de bater, então um servidor que verifica rejeita o token. Ler as claims não confere a assinatura, então o decodificador ainda mostra a versão editada.
Traduzido do Original em inglês com auxílio de IA.
Comentários
Ainda não há comentários. Seja o primeiro.


