Decodificador JWT

Substitui a entrada atual por dados de demonstração.

Resultado esperado: O cabeçalho mostra HS256 e o payload mostra sub = demo-user. A assinatura é inválida de propósito; não é um token de login.

Limitações: Decodificar não autentica o token. A verificação opcional suporta HS256/384/512; a aplicação também deve validar emissor, público e datas.

Decodificar não é verificar. Qualquer um pode ler o payload de um JWT e qualquer um pode forjar um que decodifique sem erro — um token decodificado mostra o que ele alega, nunca se isso é verdade. Tudo aqui roda no seu navegador; seu token nunca é enviado a lugar nenhum.

Nada do que você digita aqui é armazenado, registrado ou compartilhado.

Cole um JWT para ler seu cabeçalho e payload e ver quando ele expira. A decodificação acontece inteiramente no seu navegador, então o token nunca sai do seu dispositivo.

Como usar

  1. Cole o token no campo de entrada.
  2. O cabeçalho, o payload e as claims de tempo aparecem abaixo.
  3. Opcionalmente, informe o segredo para verificar uma assinatura HS256 ou HS512.

Lendo os três segmentos

Um JWT são três segmentos codificados em base64url unidos por pontos, e o base64url aqui é escrito sem padding, e é por isso que os segmentos não terminam em sinais de igual como no base64 comum.

O primeiro segmento é o header: um pequeno objeto JSON que informa o algoritmo de assinatura em alg, normalmente o tipo em typ e às vezes um identificador de chave em kid, para que quem verifica saiba contra qual de várias chaves conferir. O segundo é o payload, um objeto JSON de claims. O terceiro é a assinatura, que são bytes brutos e não JSON, por isso aparece aqui em hexadecimal.

A assinatura cobre os dois primeiros segmentos exatamente como aparecem, unidos por um ponto - o texto codificado, não o JSON que ele representa. É por isso que um token não pode ser formatado, reserializado nem ter as claims reordenadas sem ser invalidado, e é por isso que o decodificador mostra as claims, mas trata o texto original como o que realmente importa.

Decodificar não é verificar

Este é o ponto em que os JWTs são mais mal compreendidos, então vale dizer sem rodeios. O payload é codificado, não criptografado. Qualquer pessoa com o token consegue ler todas as claims. Qualquer pessoa consegue criar um token cujo payload diga o que ela quiser, e ele vai decodificar perfeitamente aqui e em qualquer lugar.

O que um token decodificado entrega é um conjunto de afirmações sem nenhuma prova. A prova é a assinatura, e conferi-la exige a chave. Até que essa verificação aconteça - com uma chave escolhida de antemão, usando um algoritmo escolhido de antemão -, o token só diz o que alguém quer que você acredite.

Na prática: nunca tome uma decisão de autorização a partir de um payload decodificado. Decodificar um token num depurador para ver o que tem dentro é normal. Ler a claim sub no código da aplicação sem verificar, porque o token passou por um gateway que supostamente já conferiu, é como serviços acabam confiando em identidades forjadas. A verificação opcional HS256 desta página existe justamente para tornar essa diferença visível.

As claims, e quem é responsável por conferi-las

A RFC 7519 registra sete claims. iss é o emissor, sub o sujeito a quem o token se refere, aud o público a que ele se destina e jti um identificador único do próprio token. As três claims de tempo - exp, nbf e iat - são valores NumericDate em segundos desde a época Unix, não em milissegundos, que é o motivo mais comum de um token montado à mão ser rejeitado.

Nenhuma delas se impõe sozinha. Um token com exp no passado só está expirado porque um verificador compara com o relógio e recusa. Um token emitido para outro público só é perigoso se ninguém conferir o aud - e é assim que um token criado para um serviço é reaproveitado contra outro que compartilha a mesma chave de assinatura. A maioria das bibliotecas confere o exp por padrão e o aud só se você disser o que esperar.

Pequenas diferenças de relógio entre as máquinas que emitem e verificam são normais, então os verificadores costumam tolerar uma defasagem de um ou dois minutos. Esta página mostra cada claim de tempo como data legível e informa se o token está dentro do período de validade no momento.

Quando um JWT é a escolha errada

Um JWT é um bearer token que carrega as próprias claims, o que o torna excelente para chamadas stateless entre serviços e desajeitado como mecanismo de sessão.

O problema é a revogação. Como o verificador só precisa da chave, não existe momento em que ele consulte um armazenamento e, portanto, não há como invalidar um token antes do exp. Faça logout de um usuário, troque a senha dele, desative a conta: todo token já emitido continua funcionando até expirar. As respostas usuais - validade muito curta com refresh tokens, ou uma lista de bloqueio de jti consultada a cada requisição - reintroduzem o estado que a ausência de estado deveria eliminar.

Onde o token fica também importa. Um token no localStorage pode ser lido por qualquer script executado na página, então uma única falha de cross-site scripting o vaza; um cookie httpOnly não, ao custo de exigir proteção contra CSRF. E como o token viaja num header em toda requisição, payloads grandes têm custo real - coloque claims demais e você vai esbarrar no limite de tamanho de header de algum proxy.

Para uma sessão web comum, um identificador opaco aleatório ligado a um armazenamento no servidor é mais simples, revogável na hora e menor.

O que a verificação faz, em ordem

Uma verificação correta é uma sequência, e é justamente onde se pula alguma etapa que moram os ataques conhecidos. Primeiro, decida o algoritmo de antemão e rejeite qualquer token cujo header discorde dele — nunca leia o alg do token e confie nele. Segundo, selecione a chave: para um segredo compartilhado ela é uma constante; para um token assimétrico é a chave pública correspondente ao kid do header, buscada no endpoint JWKS do emissor e mantida em cache.

Terceiro, recalcule a assinatura sobre os dois primeiros segmentos exatamente como eles aparecem e compare em tempo constante. Quarto, e só depois que a assinatura se confirmar, leia as claims: confira exp e nbf contra o relógio com uma pequena tolerância, confira se iss é o emissor que você espera e se aud inclui você.

A maioria das bibliotecas faz tudo isso quando configurada, e a maioria das vulnerabilidades vem de uma aplicação fazendo parte disso na mão. Decodificar para ler uma claim antes da verificação é aceitável em um depurador e perigoso no tratamento de requisições, porque naquele momento o token ainda é só uma afirmação que alguém fez.

Onde os JWTs entram no OAuth e no OpenID Connect

No OpenID Connect, o id_token é um JWT e se destina ao cliente: ele diz quem entrou, quando e de que forma. O access token é outra coisa, destinada à API, e embora muitos provedores o emitam como JWT, a especificação não exige isso — ele pode ser uma string opaca que a API valida por introspecção.

A distinção importa porque define o que a sua API deve fazer. Se o access token é opaco, a API chama o endpoint de introspecção do provedor; se é um JWT, a API o verifica localmente contra as chaves publicadas. Tratar um id_token como access token é um bug de integração comum: ele foi emitido para outra audiência, e uma API que o aceita vai aceitar tokens emitidos para qualquer aplicação atendida pelo mesmo provedor.

Escopos e papéis dentro de um token são afirmações do emissor, não permissões. Quem decide o que o chamador pode fazer continua sendo a API; o token apenas diz quem ele é e pelo que o emissor se dispôs a responder.

As vulnerabilidades que não param de voltar

O truque do alg: none declara um token sem assinatura e foi aceito por várias bibliotecas uma década atrás. A confusão de algoritmos é mais sutil: pegue um token RS256, mude o header para HS256 e assine usando a chave pública do emissor como segredo do HMAC — um verificador que lê o algoritmo do próprio token vai aceitá-lo, porque a chave pública não é segredo.

Segredos compartilhados fracos são o achado mais comum no mundo real. Um JWT contém tudo o que é preciso para testar um segredo candidato offline, na velocidade que o hardware do atacante permitir, então uma palavra de dicionário cai em segundos e deixa qualquer um emitir tokens com as claims que quiser.

Depois vêm os erros de lógica: a falta da checagem de aud, que deixa um token de um serviço autenticar em outro que compartilha a mesma chave; parâmetros kid usados para carregar uma chave a partir de um caminho sem sanitizar a entrada; e tokens aceitos pela query string, onde acabam em logs de servidor, no histórico do navegador e em cabeçalhos referrer.

Sessões ou tokens para uma aplicação web

Para uma única aplicação web com backend próprio, uma sessão no servidor com um identificador opaco em cookie é mais simples e melhor em quase todas as dimensões: a revogação é imediata, o cookie é pequeno, o conteúdo nunca sai do servidor e não há assinatura para errar. O custo é um armazenamento de sessão, que na maioria das aplicações é uma tabela ou uma chave no Redis.

Os JWTs se justificam quando o verificador não pode consultar o emissor: chamadas entre serviços através de uma fronteira de confiança, uma API usada por terceiros, ou uma borda sem estado que precisa validar requisições sem uma ida e volta. Essas são restrições reais e valem a complexidade quando você as tem.

O híbrido em que a maioria dos times chega é um access token de vida curta — minutos, não horas — com um refresh token de vida mais longa guardado em um cookie httpOnly e armazenado no servidor para poder ser revogado. Isso garante verificação sem estado no caminho comum e ainda mantém um lugar onde é possível dizer não.

Onde guardar um token no navegador

O localStorage pode ser lido por qualquer script rodando na página, então uma única falha de cross-site scripting em qualquer ponto da origem — inclusive em um script de analytics ou de publicidade de terceiros — exfiltra o token. Esse é o padrão em muitos tutoriais e é a mais fraca das opções disponíveis.

Um cookie httpOnly, Secure e com SameSite não pode ser lido por script algum, o que elimina essa classe de ataque e introduz a necessidade de proteção contra CSRF, já que o navegador anexa o cookie automaticamente. SameSite=Lax resolve a maior parte e um token anti-falsificação cobre o resto.

Manter o token apenas em memória — uma variável na aplicação, renovada a cada carregamento da página por um endpoint autenticado por cookie — é o padrão comum mais forte e o menos conveniente, já que um reload exige uma ida e volta de refresh. Qualquer que seja a escolha, o token continua viajando em um header a cada requisição, então manter o payload pequeno é uma decisão de desempenho tanto quanto de privacidade.

Perguntas frequentes

Decodificar um JWT me diz que ele é válido?
Não, e essa é a coisa mais importante a entender sobre JWTs. O payload é codificado em base64url, não criptografado nem protegido: qualquer um pode lê-lo, e qualquer um pode montar um token que decodifica perfeitamente. Só a verificação da assinatura com a chave correta prova que um token é autêntico e não foi alterado.
É seguro colar um token real aqui?
A decodificação e a verificação rodam em JavaScript nesta página. Nada é enviado, registrado ou transmitido. Ainda assim, trate qualquer JWT como uma credencial ativa: se ele vazou em outro lugar, revogue-o em vez de confiar em onde você o colou.
Por que só HS256 e HS512 podem ser verificados?
Eles são simétricos: o mesmo segredo assina e verifica, então a checagem roda localmente com o que você fornece. RS, ES e PS são assimétricos e precisam da chave pública do emissor, geralmente obtida de um endpoint JWKS, o que é outro tipo de tarefa.
O que significam exp, iat e nbf?
São claims registradas que guardam um NumericDate, medido em segundos desde a época Unix e não em milissegundos. exp é quando o token deixa de valer, iat quando ele foi emitido e nbf o primeiro momento em que pode ser usado. Esta ferramenta mostra cada um como data legível.
O que significa alg: none?
Declara um token sem assinatura. Bibliotecas que aceitam isso podem ser enganadas e aceitar tokens forjados, então é um padrão de ataque conhecido e deve ser rejeitado por qualquer verificador. Esta ferramenta nunca reporta um token assim como verificado.

Última atualização:

Referências

RFC 7519 — JSON Web Token

Alterações recentes

  • — Adicionados exemplo executável, resultados esperados, limitações e referências.

Relatar um problema

Inclua os passos, o resultado esperado e o resultado real. Remova segredos e dados pessoais.

Ferramentas relacionadas