Como decodificar um JWT
- Cole o token em Token. Uma linha inteira
Authorization: Bearer eyJ…funciona, assim como aspas em volta ou um token quebrado em várias linhas. - Leia o resultado. As três partes aparecem em cores diferentes, o header e o payload vêm formatados, e Claims lista cada claim com o significado. Horários como
expeiataparecem em horário local, em UTC e como tempo relativo, no estilo “expira em 1 hora”. - Para conferir a assinatura, cole o segredo compartilhado ou a chave pública em Verificar assinatura. O rótulo do campo segue o
algdo token: Segredo para HS256/384/512, Chave pública para todos os outros. - Leia os avisos. A ferramenta sinaliza
alg: none, tokens expirados, umnbfno futuro, a falta deexp, horários escritos em milissegundos e headers que apontam para chaves remotas (jku,x5u) ou embutem a própria chave (jwk).
Você também pode abrir um token direto com um link como /jwt-decoder/#token=eyJ…. A parte depois do # é um fragmento da URL, e os navegadores nunca enviam fragmentos ao servidor.
O que há dentro de um token
Um JWT assinado (um JWS em forma compacta) é formado por três strings Base64URL unidas por pontos: header.payload.signature. Este é um token HS256 real, emitido em 1º de janeiro de 2026 e válido por uma hora:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20iLCJzdWIiOiJ1c2VyLTQyIiwiYXVkIjoiYXBpLmV4YW1wbGUuY29tIiwiaWF0IjoxNzY3MjI1NjAwLCJleHAiOjE3NjcyMjkyMDB9.U3Gb12hN5Fnpi1rJ7nrkUzIEidkg-hPnbgiIpTah3R4
A primeira parte decodifica para o header {"alg":"HS256","typ":"JWT"}. A segunda é o payload:
{"iss":"https://auth.example.com","sub":"user-42","aud":"api.example.com","iat":1767225600,"exp":1767229200}
A terceira parte são 32 bytes de HMAC-SHA256 calculados sobre as duas primeiras, então mudar um único caractere do header ou do payload a invalida. Quase todo JWT começa com eyJ, o Base64 de {". As partes usam o alfabeto URL-safe (- e _) sem o preenchimento =; Como o JWT usa o Base64URL mostra como decodificar um à mão.
JWS ou JWE: tokens assinados e tokens criptografados
A maioria dos JWTs é JWS: assinados e legíveis por qualquer um. Um JWE é criptografado e tem cinco partes em vez de três: header.encrypted_key.iv.ciphertext.tag. O header continua legível e indica o algoritmo de gerenciamento de chave (alg, por exemplo RSA-OAEP-256 ou dir) e a cifra do conteúdo (enc, por exemplo A256GCM).
Cole um JWE aqui e a ferramenta decodifica esse header, mostra alg, enc e kid e marca o payload como criptografado. Descriptografá-lo exige a chave privada do destinatário ou a chave compartilhada, e esta ferramenta não descriptografa JWE. Se você precisa de um token cujo payload os usuários não consigam ler, o JWE é o formato certo; colocar segredos no payload de um JWS é o mesmo que colocá-los em texto puro, como explica Base64 não é criptografia.
Referência de claims do JWT
As sete primeiras linhas são as claims registradas da RFC 7519; as demais são comuns em tokens OpenID Connect e OAuth. Todo valor de tempo é um NumericDate: segundos inteiros desde 1970-01-01 UTC, nunca milissegundos.
| Claim | Nome | O que conferir |
|---|---|---|
iss | Emissor | Quem criou e assinou o token. Precisa bater com o emissor em que você confia. |
sub | Assunto | O usuário ou a entidade a que o token se refere, muitas vezes um ID de usuário. |
aud | Público | A quem o token se destina. Uma string ou um array; sua API deve rejeitar tokens endereçados a outra pessoa. |
exp | Expiração | Depois deste momento o token deve ser rejeitado. |
nbf | Não antes de | Antes deste momento o token ainda não é válido. |
iat | Emitido em | Quando foi emitido. Útil para limites de idade. |
jti | ID do JWT | Um ID único, usado para detectar replays ou revogar um único token. |
azp | Parte autorizada | O cliente OAuth para o qual o token foi emitido (OpenID Connect). |
scope, scp | Escopos | Escopos OAuth concedidos; scp é a grafia da Microsoft e da Okta. |
nonce | Nonce | Vincula um ID token do OpenID Connect à requisição de login que o pediu. |
auth_time | Momento da autenticação | Quando o usuário realmente fez login, o que pode ser bem antes do iat. |
roles, groups | Papéis, grupos | Dados de autorização adicionados pelo provedor de identidade. |
tid, oid | Tenant, ID de objeto | Identificadores do tenant e do objeto de usuário no Microsoft Entra ID. |
O header tem os próprios parâmetros: alg (o algoritmo de assinatura), typ (normalmente JWT, ou at+jwt para access tokens OAuth), kid (qual chave assinou) e cty (definido como JWT quando um token está aninhado dentro de outro).
Verificar a assinatura: qual chave colar
Só a verificação da assinatura mostra de onde um token veio, e a chave necessária depende da família de algoritmos indicada no header.
alg | Chave a colar | Tamanho da assinatura |
|---|---|---|
| HS256, HS384, HS512 | O segredo compartilhado. Ajuste O segredo está em para Texto, Base64/Base64URL ou Hex conforme ele estiver guardado; um JWK oct também funciona. | 32, 48, 64 bytes |
| RS256–RS512, PS256–PS512 | A chave pública RSA: PEM BEGIN PUBLIC KEY, PEM BEGIN RSA PUBLIC KEY, um certificado X.509, um JWK ou um JWKS. | O tamanho da chave; 256 bytes para RSA-2048 |
| ES256, ES384, ES512 | A chave pública EC em P-256, P-384 ou P-521, em qualquer uma das formas acima. | 64, 96, 132 bytes (r‖s bruto) |
| EdDSA | Uma chave pública Ed25519 em PEM ou um JWK OKP. | 64 bytes |
Para tokens de um provedor de identidade, as chaves públicas ficam no jwks_uri indicado em https://<issuer>/.well-known/openid-configuration. Esta página não consegue buscar essa URL porque não consegue se conectar a outros servidores, então abra-a numa nova aba e cole o JSON. Com um JWKS, a chave é escolhida pelo kid; se o token não tiver kid, todas as chaves compatíveis são testadas.
Assinaturas ECDSA em formato DER (geralmente de 70 a 72 bytes para ES256, em vez de 64) são detectadas, convertidas e sinalizadas, porque o JWS exige r‖s bruto e muitas bibliotecas rejeitam DER. Colar uma chave privada também funciona (a metade pública é derivada), embora a verificação nunca precise dela. ES256K e Ed448 não são suportados, porque o WebCrypto não os oferece.
Se um token HS256 falha com um segredo do qual você tem certeza, muitas vezes o segredo está codificado em Base64 em algum ponto da sua configuração e o servidor o decodifica antes de usar. Troque O segredo está em para Base64 e tente de novo.
Por que decodificar um token aqui é seguro
Um JWT num header Authorization é uma credencial válida até expirar. Se você cola um token de produção ativo numa página web que o envia para um servidor, quem controla esse servidor pode reutilizá-lo contra a sua API, e de fora normalmente não dá para saber se uma página faz isso.
Nesta página, a decodificação e a verificação da assinatura com WebCrypto rodam no seu navegador. A página também traz uma Content Security Policy cuja diretiva connect-src só permite /cdn-cgi/rum, onde o Cloudflare Web Analytics conta as visitas, então o navegador bloqueia qualquer outra requisição fetch, XHR, WebSocket ou beacon que a página tentar. Você pode confirmar por conta própria: abra as ferramentas de desenvolvedor na aba Network e cole um token, ou desligue o Wi-Fi depois que a página carregar e continue decodificando.
Mesmo assim, prefira tokens de teste ou tokens prestes a expirar, e se um token de produção foi colado em algum lugar que você não controla, revogue a sessão.
Tokens expirados, nbf e diferença de relógio
exp e nbf são conferidos com o relógio de quem verifica, e relógios se desajustam. Um token emitido por um servidor cujo relógio está 30 segundos adiantado pode chegar com iat e nbf no futuro e ser rejeitado como “ainda não válido”. Por isso as bibliotecas de JWT aceitam uma pequena tolerância: leeway no PyJWT, clockTolerance no jsonwebtoken e no jose.
Este decodificador compara os horários com o relógio do seu aparelho e descreve o resultado em palavras: “expirou há 2 dias” para exp, “ainda não é válido” com o tempo restante para nbf, ou um aviso de que o iat está no futuro, o que aponta para o relógio do emissor. Um valor como 1767229200000 é sinalizado como milissegundos; lido como segundos, ele cai dezenas de milhares de anos no futuro, um bug comum quando o código usa Date.now() em vez de Math.floor(Date.now() / 1000).
Para ler as claims no código sem verificar, a biblioteca padrão do Python basta:
import base64, json
def b64url_decode(part):
return base64.urlsafe_b64decode(part + "=" * (-len(part) % 4))
header_b64, payload_b64, signature_b64 = token.split(".")
print(json.loads(b64url_decode(payload_b64)))
Em Node.js, JSON.parse(Buffer.from(payload_b64, "base64url").toString("utf8")) faz o mesmo. Para decisões de autorização, use uma biblioteca que verifique a assinatura e fixe os algoritmos aceitos. Há mais trechos nas páginas de Python e Node.js.
Para gerar ou assinar de novo um token para testes, use o codificador de JWT. Um único segmento pode ser decodificado sozinho com o decodificador Base64URL.
Perguntas frequentes
Dá para decodificar um JWT sem a chave secreta?
Dá. O header e o payload são só JSON codificado em Base64URL, então qualquer pessoa com o token consegue lê-los. O segredo ou a chave pública só são necessários para conferir se a assinatura é autêntica.
Por que o decodificador diz que a assinatura é inválida?
Geralmente a chave está errada ou no formato errado. Para HS256, veja se o segredo está guardado como Base64 ou hex e ajuste O segredo está em de acordo. Para RS256 ou ES256, confira se a chave pública corresponde ao kid do token; colando um JWKS inteiro, a ferramenta escolhe a chave pelo kid para você.
Como ver quando um JWT expira?
Olhe a claim exp. Ela é uma contagem de segundos desde 1970-01-01 UTC, e a tabela de claims a mostra em horário local, em UTC e como tempo relativo, por exemplo “expirou há 2 dias”. Um token sem exp nunca expira por conta própria.
Esta ferramenta descriptografa um JWE?
Não. Para um token criptografado de cinco partes, ela decodifica o header protegido e mostra alg, enc e kid. Descriptografar o payload exigiria a chave privada do destinatário ou a chave compartilhada.
O token é enviado para algum lugar quando eu colo?
Não. A decodificação e a verificação rodam no seu navegador com JavaScript e WebCrypto, e a Content Security Policy da página bloqueia todas as requisições de rede, exceto as do contador de visitas da Cloudflare.