JWTs estão em todo lugar. Toda vez que você faz login em uma web app, uma API emite um JSON Web Token, e esse token carrega sua identidade, suas permissões e muitas vezes alguns dados pessoais em seu payload. O formato em si foi estável por uma década, depois veio uma enxurrada de atividade em 2024-2025 — RFC 8725 (melhores práticas atuais para JWT) tornou-se um requisito obrigatório para novas especificações, o debate “JWTs são ruins” se reacendeu com o tamanho de sessões, e vários grandes provedores migraram para tokens opacos para uso no navegador. O resultado: mais desenvolvedores do que nunca estão inspecionando tokens manualmente. Quando algo dá errado — sua sessão expira no horário errado, uma API rejeita um token que você pensava ser válido, um colega diz “o que tem no JWT?” — a primeira coisa que a maioria dos desenvolvedores faz é colar o token em um decodificador online.
O problema: a maioria desses decodificadores envia seu token para um servidor. O token em si não é um segredo (é apenas JSON codificado em base64), mas o conteúdo do payload frequentemente é: um ID de usuário, um e-mail, às vezes um ID de sessão, às vezes uma lista de permissões. Se seu serviço usa JWTs para se comunicar com outros serviços internos, o payload pode até incluir nomes de serviços internos ou flags de funcionalidade.
Um token colado em um decodificador de terceiros é um pequeno vazamento de informação. Na maioria das vezes não importa. Mas o princípio importa: você deveria ser capaz de inspecionar um token sem confiar na infraestrutura de outra pessoa.
Como um JWT realmente parece
Um JWT são três strings codificadas em base64url, separadas por pontos:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NSIsIm5hbWUiOiJBbGljZSIsImlhdCI6MTUxNjIzOTAyMn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
As três partes são o header, payload e assinatura. Decodifique as duas primeiras e você obtém JSON:
// Header
{
"alg": "HS256",
"typ": "JWT"
}
// Payload
{
"sub": "12345",
"name": "Alice",
"iat": 1516239022
}
A assinatura é um hash criptográfico que prova que o token foi emitido por alguém que conhece o segredo. Qualquer pessoa pode decodificar o payload — essa não é a fronteira de segurança. A fronteira de segurança é se você pode verificar a assinatura.
A distinção entre verificação e decodificação
É aqui que muitos desenvolvedores erram. Decodificar não é verificar. Um decodificador apenas decodifica base64 o JSON para que você possa ler. Qualquer pessoa pode fazer isso, e isso não prova que o token é autêntico. Verificação é o ato de checar a assinatura contra um segredo conhecido para confirmar que o token não foi adulterado.
- Para debugar o conteúdo de um token (quais claims ele tem, quando expira), decodificação é suficiente.
- Para autenticar um usuário, você precisa de verificação, e ela tem que acontecer em um servidor no qual você confia.
A maioria das ferramentas decodificadoras online apenas decodifica. Elas exibem o header e payload, mas nunca pedem seu segredo — porque não estão verificando, apenas mostrando o que está no token.
Como decodificar localmente
Você não precisa de uma ferramenta de terceiros para isso. Um JWT são apenas três strings base64url. Abra um terminal:
echo 'eyJzdWIiOiIxMjM0NSIsIm5hbWUiOiJBbGljZSIsImlhdCI6MTUxNjIzOTAyMn0' | tr '_-' '/+' | base64 -d
Esse é o payload. O header é o primeiro segmento, o mesmo truque.
Se você preferir não memorizar o passo tr '_-' '/+', o decodificador de JWT no DevSpeedTools faz a mesma coisa no navegador. Nenhuma requisição de rede, nenhum upload, nenhum log. Abra DevTools → Network, cole um token e confirme você mesmo que nada sai da sua máquina.
Quando você realmente precisa de verificação
Se você está tentando debugar um problema de autenticação e precisa saber se o token é válido (não apenas o que contém), precisa verificar a assinatura. A verificação tem que acontecer com o mesmo segredo ou chave pública que seu servidor de autenticação usa. Isso significa que tem que acontecer em infraestrutura que você controla.
Algumas opções de verificação que não envolvem colar seu segredo em um site:
- Em Node.js:
jsonwebtoken.verify(token, process.env.JWT_SECRET). - Em Python:
jwt.decode(token, key, algorithms=['HS256']). - Em Go:
token, err := jwt.Parse(tokenString, keyFunc). - CLI:
jwt-cli(Rust) oupyjwtcom uma one-liner.
Se você se encontrar precisando de um verificador online por algum motivo, procure um que diga explicitamente que roda no navegador (o código-fonte geralmente é visível). As ferramentas honestas dizem isso. As demais você deve assumir que enviam seu token para um servidor.
O erro “invalid signature”
Uma razão comum pela qual desenvolvedores acabam em um decodificador é o erro invalid signature. Essa mensagem está fazendo duas coisas:
- Dizendo que o token foi assinado com um segredo diferente do que você está usando para verificar.
- Dizendo que o token pode ter sido adulterado.
Ou — e essa é a que a maioria perde — o token pode estar expirado. Verifique a claim exp no payload. Se o timestamp Unix atual passou de exp, o token é inválido. Algumas bibliotecas lançam invalid signature para tokens expirados, o que é enganoso.
O decodificador de JWT mostra o valor de exp ao lado do resto do payload para que você possa identificar tokens expirados de relance. O mesmo vale para nbf (não antes), iat (emitido em) e aud (audiência) — todos úteis para debug.
O resumo
Decodificadores de JWT são úteis. Também são um lugar onde desenvolvedores ficam descuidados ao colar tokens de produção. Um padrão mais seguro:
- Use um decodificador local ou no navegador para inspeção rápida. Sem upload, sem vazamento.
- Use uma CLI ou seu próprio código para verificação. Nunca cole um segredo em um site.
- Verifique as claims padrão primeiro —
expexpirado é a causa da maioria dos problemas “meu token de repente parou de funcionar”.
O token não é um segredo. O conteúdo do token frequentemente é. Trate de acordo.