Descodificar um JSON Web Token (JWT)

descodifica o seu token JWT (JSON Web Token) e mostra as informações que contém de forma legível e estruturada

O que é um JWT (JSON Web Token)?

Um JSON Web Token, abreviado JWT (pronuncia-se "jot"), é um formato compacto definido pela RFC 7519 que permite transportar uma série de reivindicações (claims) entre duas partes. O JWT, ou jeton JWT, é hoje o formato dominante para veicular uma identidade autenticada numa API HTTP. Um JWT apresenta-se como uma cadeia ASCII composta por três segmentos separados por pontos:

header.payload.signature

Cada segmento é codificado em Base64URL, uma variante de Base64 sem padding = e que substitui + por - e / por _ para poder circular num URL ou num cabeçalho HTTP sem escape adicional.

Importante: um JWT NÃO está cifrado. O formato JWT padrão (JWS) é simplesmente assinado: a assinatura garante a integridade do conteúdo, mas não traz qualquer confidencialidade. Qualquer pessoa pode descodificar o payload de um JWT com um simples Base64URL inverso, como faz esta ferramenta jwt decode online.

Anatomia de um JWT

Um json web token é composto por três partes bem distintas, cada uma desempenhando um papel preciso no mecanismo de autenticação:

1. Header

O header é um objeto JSON que descreve como o token é assinado. Contém no mínimo:

  • alg (algorithm): o algoritmo de assinatura utilizado. Valores típicos: HS256, RS256, ES256, EdDSA.
  • typ (type): o tipo do token, quase sempre "JWT".
  • kid (key ID): facultativo, identifica que chave deve ser utilizada para verificar a assinatura. Prático na presença de um parque de chaves em rotação (JWKS).

2. Payload

O payload contém as claims, ou seja as reivindicações que o emissor faz a respeito do utilizador ou da sessão. A RFC 7519 define sete claims padrão (registered claims):

  • iss (issuer): quem emitiu o token, por exemplo "https://accounts.google.com".
  • sub (subject): a quem pertence o token, na prática o identificador do utilizador.
  • aud (audience): a quem se destina o token. Evita que um token emitido para a API A seja aceite pela API B.
  • exp (expiration time): timestamp Unix após o qual o token deixa de ser válido.
  • nbf (not before): timestamp antes do qual o token ainda não está ativo.
  • iat (issued at): timestamp de emissão do token.
  • jti (JWT ID): identificador único do token, utilizado para a revogação e a prevenção de replay.

A estas claims padrão acrescentam-se geralmente claims custom próprias da aplicação (roles, scope, tenant_id, email, permissions...).

3. Signature

A assinatura é um resumo criptográfico calculado sobre base64url(header) + "." + base64url(payload) com uma chave. É ela que prova que ninguém modificou o header nem o payload desde a emissão. Os algoritmos mais comuns:

  • HS256 / HS384 / HS512: assinatura simétrica HMAC-SHA. Uma chave secreta partilhada entre o emissor e o verificador. Simples, mas inadequada assim que há mais do que um consumidor.
  • RS256 / RS384 / RS512: assinatura assimétrica RSA. O emissor assina com a sua chave privada, qualquer consumidor verifica com a chave pública correspondente. Padrão de facto para OAuth2 e OpenID Connect.
  • ES256 / ES384 / ES512: assinatura assimétrica ECDSA. Mesmas propriedades que RS256 mas com chaves e assinaturas muito mais curtas.
  • EdDSA (Ed25519): assinatura assimétrica moderna, rápida e compacta.

Mais uma vez: a assinatura protege a integridade, não a confidencialidade. O payload permanece legível por quem possui o token.

Porquê descodificar um JWT?

A operação jwt token decode responde a várias necessidades concretas para um programador ou um engenheiro de segurança:

  • Debug de autenticação: a sua API devolve um 401 ou um 403, quer ver o que está realmente no payload (sub, scope, roles, exp) em vez de adivinhar.
  • Verificar as claims: confirmar que um token contém mesmo a reivindicação esperada (por exemplo tenant_id ou permissions) antes de procurar noutro lado da cadeia de autorização.
  • Ler a expiração: converter o timestamp exp em data humana para confirmar que um token está mesmo expirado, ou, pelo contrário, que ainda devia ser válido.
  • Auditoria de segurança: certificar-se de que um serviço terceiro não fuga informações sensíveis no payload (e-mails, identificadores internos, dados pessoais).
  • Formação e compreensão: ver concretamente como é um jsonwebtoken que sai de um fornecedor OAuth (Google, Auth0, Keycloak, AWS Cognito) para perceber a mecânica sem mergulhar na documentação.
  • Exploração de tokens públicos: inspecionar um JWT encontrado em logs, num cookie ou numa troca OAuth intercetada.

Decoder vs Verifier: a distinção crítica

As duas operações parecem próximas mas nada têm a ver em termos de garantias de segurança:

  • Descodificar um JWT consiste em dividir a cadeia pelos . e aplicar um Base64URL inverso aos dois primeiros segmentos. É uma simples leitura, ao alcance de qualquer script de três linhas. Não é feita qualquer verificação de assinatura.
  • Verificar um JWT consiste em recalcular a assinatura a partir do header, do payload e de uma chave, e comparar o resultado com a assinatura presente no token. É isto que garante que o token não foi falsificado.

Conclusão prática: descodificar não é confiar. Enquanto a assinatura não tiver sido verificada com a chave certa, o conteúdo do payload pode ser totalmente falso. Para a fase de confiança, utilize o nosso JWT Verifier.

Como utilizar

  1. Obtenha o JWT a inspecionar, por exemplo a partir de um cabeçalho Authorization: Bearer <jwt>, de um cookie de sessão, do localStorage do navegador, ou de um log aplicacional.
  2. Cole a cadeia completa no campo de entrada. Os três segmentos devem permanecer separados por pontos.
  3. A ferramenta mostra imediatamente o header descodificado em JSON formatado, com o algoritmo e o tipo.
  4. O payload é depois descodificado e mostrado. Vê aí todas as claims padrão e custom.
  5. A ferramenta também indica a informação de assinatura (algoritmo declarado, comprimento), sem a verificar.
  6. Para confirmar que o token não foi falsificado, mude para o nosso JWT Verifier com a chave pública ou o segredo esperado.

Toda a descodificação é efetuada no seu navegador em JavaScript: o seu token nunca é enviado para os nossos servidores.

JWT e segurança: armadilhas a evitar

NUNCA armazene dados sensíveis no payload de um JWT assinado.

Palavras-passe, números de cartão bancário, dados médicos, segredos de API, identificadores internos críticos: tudo o que está no payload é legível por quem possui o token, incluindo o próprio utilizador através das ferramentas de programador do seu navegador. A assinatura não esconde nada, apenas prova que o emissor é quem afirma ser.

Algumas regras de ouro para usar bem os JWT em produção:

  • Verificar sempre a assinatura no servidor antes de conceder qualquer direito. O nosso JWT Verifier ilustra exatamente esta operação.
  • Preferir RS256 ou ES256 a HS256 para APIs públicas. A assinatura assimétrica evita partilhar um segredo entre o emissor e cada consumidor.
  • Respeitar sempre a claim exp. Um JWT sem expiração ou com uma expiração demasiado distante é uma bomba-relógio em caso de fuga.
  • Validar iss e aud no servidor, para evitar que um token legítimo emitido para outro serviço seja aceite por engano.
  • Recusar alg: "none" na verificação. É uma falha clássica que permite a um atacante forjar qualquer payload.
  • Manter durações de vida curtas (15 minutos, por exemplo) e combinar com um refresh token mais longo mas revogável no servidor.

Exemplo de token JWT descodificado

Eis um JWT típico:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjMiLCJuYW1lIjoiSm9obiIsImlhdCI6MTUxNjIzOTAyMn0.jrU9j8LZcRK2_BZjqXjU7lEpJbkqmXfTQIu9vT45j-I

Uma vez descodificado, eis o seu conteúdo:

// Header
{
  "alg": "HS256",
  "typ": "JWT"
}

// Payload
{
  "sub": "123",
  "name": "John",
  "iat": 1516239022
}

// Signature (binaire, encodé en Base64URL)
HMACSHA256(
  base64url(header) + "." + base64url(payload),
  secret
)

Onde encontrar um JWT para copiar?

Na prática, um JWT para decifrar (no sentido de descodificar) vem mais frequentemente de um destes locais:

  • Cookie HTTP: abra as ferramentas de programador (F12), separador Application ou Storage, depois Cookies. Identifique um cookie chamado access_token, jwt, session ou semelhante.
  • localStorage / sessionStorage: mesmo painel, secção Local Storage. Muitas SPA armazenam aí o seu token numa chave token ou auth.
  • Cabeçalho Authorization: separador Network, selecionar um pedido de API, ler o cabeçalho Authorization: Bearer <jwt>. Copiar apenas a parte depois de Bearer .
  • Logs do servidor: um JWT aparece por vezes nos logs de uma gateway ou de um reverse proxy (a evitar em produção, mas útil em debug).

Perguntas frequentes

O JWT é cifrado ou em claro?

Um JWT assinado (formato JWS) está apenas codificado em Base64URL, não cifrado. Qualquer pessoa que intercete um token pode ler o payload em segundos. Se tiver de transportar dados realmente confidenciais no token, é preciso utilizar o formato JWE (JSON Web Encryption), que adiciona uma camada de cifragem por cima da assinatura. Na prática, o JWE continua raro: prefere-se não colocar dados sensíveis num token e manter as informações críticas em base no servidor.

Como revogar um JWT antes da sua expiração?

É um dos pontos fracos do JWT: por construção, o servidor não precisa de armazenar o estado do token, portanto também não sabe como o marcar como revogado. Existem três abordagens. Lista de revogação: manter no servidor a lista dos jti invalidados, e consultá-la em cada pedido. Durações de vida curtas: emitir access tokens válidos 5 a 15 minutos, e utilizar um refresh token revogável no servidor para gerar novos. Rotação da chave de assinatura: invalidar toda uma geração de tokens mudando a chave. A segunda abordagem é de longe a mais difundida.

Qual a diferença entre um JWT e uma sessão clássica?

Uma sessão clássica armazena um identificador opaco no lado do cliente (geralmente num cookie) e conserva todos os dados associados (utilizador, direitos, expiração) em memória ou em base no servidor. Um JWT, pelo contrário, transporta diretamente esses dados no token assinado. Vantagem do JWT: o servidor não precisa de armazenar sessão, o que simplifica o escalamento horizontal e a arquitetura de microsserviços. Inconvenientes: a revogação é mais complexa, o token é mais volumoso em cada pedido, e a mínima fuga expõe o payload.

Diferença entre JWT, JWS e JWE?

JWT (RFC 7519) é um formato de token genérico. Pode ser implementado de duas formas concretas: JWS (RFC 7515, JSON Web Signature) que se limita a assinar o payload, e JWE (RFC 7516, JSON Web Encryption) que o cifra. Na prática, quando se fala de "JWT" sem precisão, fala-se quase sempre de um JWS: um token assinado mas legível por todos. O JWE é utilizado em contextos onde a confidencialidade do payload é indispensável, por exemplo em alguns cenários OpenID Connect avançados.

O meu JWT não é aceite pela API, porquê?

As causas clássicas são, por ordem de frequência: token expirado (verifique a claim exp), assinatura inválida (chave secreta ou chave pública não corresponde à utilizada pelo emissor), mau aud (o token foi emitido para outro serviço), mau iss (o emissor declarado não é o esperado), algoritmo recusado (a API exige por exemplo RS256 e recebe um HS256), relógios dessincronizados entre o emissor e o verificador (joga com exp e nbf). Descodificar o token com esta ferramenta permite já eliminar metade das hipóteses lendo diretamente as claims.

Como gerar um JWT?

A maioria das linguagens dispõe de uma biblioteca dedicada: jsonwebtoken em Node.js, PyJWT em Python, lcobucci/jwt ou firebase/php-jwt em PHP, jjwt em Java, golang-jwt/jwt em Go. Todas recebem na entrada um objeto payload, uma chave e um algoritmo, e devolvem a cadeia header.payload.signature pronta a enviar. É fortemente desaconselhado implementar a geração à mão: a criptografia comporta demasiadas armadilhas (comparações não constantes, gestão incorreta de alg: none, etc.).

O decoder aceita um JWT expirado?

Sim. O decoder limita-se a mostrar o conteúdo do token sem fazer juízo sobre a sua validade temporal. Não avalia nem exp, nem nbf, nem a assinatura. É útil para perceber porquê um token foi rejeitado por uma API: pode-se comparar o valor de exp com a hora atual para confirmar que está mesmo expirado.

O meu JWT é válido se o decoder o mostra corretamente?

Não. A apresentação prova apenas que a cadeia está bem formada (três segmentos separados por pontos, codificação Base64URL correta, JSON válido no header e no payload). Não diz nada sobre a autenticidade do token. Um JWT totalmente falsificado pode apresentar-se sem erro num decoder, é precisamente para isso que se deve passar a um verifier.

Exemplo de pedido

curl -X POST https://cdrn.fr/api/v1/tools/jwt-decoder/execute \
  -H "Content-Type: application/json" \
  -d '{"token":"..."}'

Esquema de entrada

Campo Tipo Obrigatório Predefinição
token text

Pontos de acesso

  • GET https://cdrn.fr/api/v1/tools - lista todas as ferramentas disponíveis
  • GET https://cdrn.fr/api/v1/tools/jwt-decoder - obtém o esquema desta ferramenta
  • POST https://cdrn.fr/api/v1/tools/jwt-decoder/execute - executa esta ferramenta com um payload JSON