jwt decode security authentication tokens

Entendendo JWTs: Como Decodificar e Gerar JSON Web Tokens

Um guia abrangente sobre JSON Web Tokens (JWT). Aprenda a decodificar, verificar e gerar tokens para depuração de autenticação segura.

Introdução: O que é um JSON Web Token?

JSON Web Token (JWT) é um padrão aberto (RFC 7519) que define uma forma compacta e autocontida de transmitir informações com segurança entre partes como um objeto JSON. Essas informações podem ser verificadas e consideradas confiáveis porque são assinadas digitalmente. JWTs podem ser assinados usando um segredo (algoritmo HMAC) ou um par de chaves pública/privada (RSA ou ECDSA).

Os JWTs foram criados para resolver um desafio comum em sistemas distribuídos: como um servidor pode confiar em uma requisição de um cliente sem precisar consultar uma sessão no banco de dados? A resposta é codificar e assinar a identidade e as permissões do usuário diretamente em um token que o cliente carrega em cada requisição.

Hoje, os JWTs são a espinha dorsal da autenticação e autorização modernas:

  • Single Sign-On (SSO): Um único login concede acesso a múltiplos serviços.
  • Autenticação de API: Aplicações móveis e SPAs autenticam chamadas à API com um Bearer token.
  • OAuth 2.0 / OpenID Connect: JWTs são usados como access tokens e ID tokens.
  • Microsserviços: Serviços verificam a identidade do chamador sem um armazenamento central de sessões.

Estrutura do JWT: header.payload.signature

Um JWT é uma string de três partes codificadas em Base64url, separadas por pontos (.):

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Parte 1 — Header (Cabeçalho) decodificado:

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

O cabeçalho especifica o algoritmo de assinatura (alg) e o tipo de token (typ).

Parte 2 — Payload (Carga útil) decodificado:

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

O payload contém os claims — declarações sobre a entidade (geralmente um usuário) e metadados adicionais.

Parte 3 — Signature (Assinatura) (para HS256) calculada como:

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

A assinatura garante que o token não foi adulterado. Nota crítica: O payload é apenas codificado em Base64url, não criptografado. Qualquer pessoa que obtiver o JWT pode decodificar e ler todos os claims.

Algoritmos de Assinatura: HS256, RS256 e ES256

HS256 (HMAC-SHA256) — Simétrico

Usa um único segredo compartilhado tanto para assinar quanto para verificar. Simples de implementar, mas o mesmo segredo deve ser conhecido pelo emissor e pelo verificador.

  • Ideal para: Aplicações monolíticas ou serviços fortemente acoplados que compartilham um segredo.
  • Risco: Se o segredo vazar, todos os tokens podem ser forjados.

RS256 (RSA-SHA256) — Assimétrico

Usa uma chave privada para assinar e uma chave pública para verificar. A chave privada permanece secreta; a pública pode ser compartilhada livremente via endpoint JWKS.

  • Ideal para: Sistemas distribuídos, microsserviços e cenários onde múltiplos serviços verificam tokens.
  • Tamanho de chave: Mínimo de 2048 bits para RSA recomendado.

ES256 (ECDSA-SHA256) — Assimétrico

Usa o Algoritmo de Assinatura Digital de Curva Elíptica com a curva P-256. Produz assinaturas menores que RS256 com segurança equivalente.

  • Ideal para: Ambientes com restrições de desempenho ou largura de banda.
Algoritmo Tipo Chave Tamanho da assinatura Caso de uso
HS256 Simétrico Segredo compartilhado 32 bytes Apps de único serviço
RS256 Assimétrico Par de chaves RSA 256+ bytes Sistemas distribuídos
ES256 Assimétrico Par de chaves EC 64 bytes APIs de alto desempenho

Claims JWT: Registrados, Públicos e Privados

Claims são declarações sobre uma entidade (geralmente um usuário) e metadados codificados no payload.

Claims Registrados (definidos pela IANA)

Claim Nome completo Descrição
iss Issuer Quem emitiu o token (ex: "auth.example.com")
sub Subject A quem o token se refere (ex: um ID de usuário)
aud Audience Para quem o token é destinado (identificador de serviço)
exp Expiration Timestamp Unix após o qual o token é inválido
nbf Not Before O token não deve ser usado antes deste timestamp
iat Issued At Timestamp Unix de quando o token foi emitido
jti JWT ID Identificador único para prevenir ataques de replay

Claims Públicos

Definidos no Registro de Claims JWT da IANA. Exemplos: email, name, picture, roles.

Claims Privados

Claims personalizados acordados entre emissor e consumidor. Use nomes com namespace para evitar colisões:

{
  "https://example.com/tenant_id": "acme-corp",
  "https://example.com/roles": ["admin", "editor"]
}

Como Funciona o Fluxo de Autenticação JWT

  1. Login do usuário: O cliente envia credenciais (usuário + senha) ao servidor de autenticação.
  2. Emissão do token: O servidor valida as credenciais, cria um JWT assinado com os claims apropriados e o retorna ao cliente.
  3. Armazenamento do token: O cliente armazena o JWT (em memória, localStorage ou um cookie HttpOnly).
  4. Requisições autenticadas: Para cada requisição a um recurso protegido, o cliente inclui o JWT no cabeçalho Authorization:
    Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
    
  5. Verificação do token: O servidor extrai o token, verifica a assinatura, checa exp e concede ou nega acesso com base nos claims.
  6. Renovação do token: Quando o access token expira, o cliente usa um refresh token de longa duração para obter um novo sem se reautenticar.
Cliente           Servidor Auth         Servidor de Recursos
  |                    |                     |
  |-- POST /login ---->|                     |
  |<-- 200 + JWT ------|                     |
  |                    |                     |
  |-- GET /api (Authorization: Bearer JWT) ->|
  |                    |   verificar JWT     |
  |<----------- 200 + dados ---------------->|

Considerações de Segurança

O Payload NÃO É Criptografado

Codificação Base64url não é criptografia. Qualquer pessoa que tenha um JWT pode decodificar e ler todos os claims instantaneamente. Nunca inclua em um payload JWT:

  • Senhas ou hashes de senhas
  • Números de cartão de crédito ou dados financeiros
  • Informações pessoais sensíveis (PII) além do necessário
  • Chaves privadas ou segredos internos

Sempre Verifique a Assinatura

// Node.js — biblioteca jsonwebtoken
const jwt = require("jsonwebtoken");

try {
  const decoded = jwt.verify(token, process.env.JWT_SECRET);
  console.log(decoded.sub); // ID de usuário confiável
} catch (err) {
  res.status(401).json({ error: "Token inválido ou expirado" });
}

Use Tempos de Expiração Curtos

Access tokens devem ter ciclos de vida curtos (15 minutos a 1 hora). Use refresh tokens para sessões longas e limitar o impacto de um token roubado.

Sempre Use HTTPS

Nunca transmita tokens por conexões não criptografadas. Um token interceptado é tão perigoso quanto uma senha roubada.

Vulnerabilidades Comuns

1. Ataque de Confusão de Algoritmo (CVE-2015-9235)

Um atacante muda o campo alg no cabeçalho de RS256 para HS256 e assina o token usando a chave pública do servidor como segredo HMAC. Um servidor mal implementado aceita o token forjado.

Mitigação: Especifique sempre o algoritmo esperado explicitamente no servidor:

jwt.verify(token, publicKey, { algorithms: ["RS256"] });

2. O Ataque do Algoritmo "none"

Se um servidor aceita alg: "none", um atacante pode criar tokens sem nenhuma assinatura.

Mitigação: Rejeite explicitamente tokens com alg: "none". Bibliotecas modernas corrigiram isso, mas versões antigas podem ser vulneráveis.

3. Segredos Fracos (HS256)

Um segredo HMAC curto ou fácil de adivinhar pode ser quebrado por força bruta offline com ferramentas como hashcat contra um token capturado.

Mitigação: Use um segredo aleatório criptograficamente seguro de pelo menos 256 bits:

openssl rand -hex 32

4. Validação de Claims Ausente

Não validar iss, aud ou nbf permite reutilização de tokens entre serviços ou uso antes do período válido.

5. Armazenamento Inseguro de Tokens

localStorage é acessível por qualquer JavaScript na página, tornando tokens vulneráveis a ataques XSS. Prefira cookies HttpOnly para tokens sensíveis.

JWT vs Tokens de Sessão: Sem Estado vs Com Estado

Característica JWT (Sem estado) Token de sessão (Com estado)
Armazenamento Lado do cliente Lado do servidor (BD ou cache)
Escalabilidade Excelente — sem consulta ao servidor Requer armazenamento de sessão compartilhado
Revogação Difícil — válido até exp Fácil — excluir do armazenamento
Tamanho do token Maior por requisição Token pequeno, dados no servidor
Microsserviços Ideal — verificação independente Requer infraestrutura compartilhada
Visibilidade Qualquer um com o token pode ler Dados ficam apenas no servidor

Escolha JWT ao construir sistemas distribuídos, APIs REST sem estado ou aplicações móveis. Escolha sessões quando precisar de revogação imediata (ex: "sair de todos os dispositivos").

O Desafio da Revogação

Como JWTs são autocontidos, você não pode cancelar um token antes de expirar sem infraestrutura adicional:

  • Expiração curta + refresh tokens: Access tokens expiram rapidamente; revogue refresh tokens no BD.
  • Lista negra de tokens: Armazene jti revogados no Redis (reintroduz alguma gestão de estado).
  • Rotação de segredos: Rotacione o segredo de assinatura para invalidar todos os tokens (impacta todos os usuários).

OAuth 2.0 e OpenID Connect

OAuth 2.0

OAuth 2.0 é um framework de autorização que não exige um formato de token específico. Porém, JWTs são amplamente usados como access tokens OAuth porque são autocontidos e carregam escopos de autorização:

{
  "iss": "https://auth.example.com",
  "sub": "user_123",
  "aud": "https://api.example.com",
  "scope": "read:profile write:posts",
  "exp": 1893456000
}

OpenID Connect (OIDC)

OpenID Connect é uma camada de identidade construída sobre o OAuth 2.0. Ele introduz o ID Token, que é sempre um JWT contendo claims de identidade sobre o usuário autenticado:

{
  "iss": "https://accounts.google.com",
  "sub": "110169484474386276334",
  "aud": "my-client-id.apps.googleusercontent.com",
  "email": "[email protected]",
  "name": "Jane Doe",
  "exp": 1893456000,
  "iat": 1893452400
}

O OIDC também define o endpoint JWKS (/.well-known/jwks.json), onde o servidor de autorização publica suas chaves públicas. Qualquer serviço pode buscar essas chaves para verificar tokens sem uma troca prévia de chaves.

Boas Práticas

  1. Use algoritmos assimétricos (RS256/ES256) para sistemas públicos — proteja a chave privada de assinatura enquanto qualquer um pode verificar com a chave pública.
  2. Defina valores exp curtos para access tokens — 15 minutos é um padrão seguro e comum.
  3. Sempre rotacione refresh tokens — emita um novo a cada uso e invalide o anterior.
  4. Valide todos os claims relevantes — verifique no mínimo iss, aud, exp e nbf.
  5. Especifique o algoritmo esperado explicitamente — nunca confie apenas no campo alg do cabeçalho do token.
  6. Nunca coloque dados sensíveis no payload — ele é codificado, não criptografado.
  7. Sempre use HTTPS — nunca transmita tokens por conexões não criptografadas.
  8. Armazene tokens com segurança — prefira cookies HttpOnly, Secure, SameSite=Strict ao localStorage.
  9. Implemente uma estratégia de revogação de tokens — use lista negra ou tokens de curta duração com rotação de refresh tokens.
  10. Mantenha bibliotecas JWT atualizadas — novas versões incluem correções de segurança.

Perguntas Frequentes (FAQ)

P: Posso descriptografar o payload de um JWT? R: O payload de um JWT é codificado em Base64url, não criptografado — qualquer um pode lê-lo sem nenhuma chave. Se precisar de confidencialidade, use JWE (JSON Web Encryption, RFC 7516), que de fato criptografa o payload.

P: Qual é a diferença entre decode e verify? R: decode apenas decodifica as partes em Base64url e retorna o JSON sem verificações de segurança. verify também valida a assinatura com sua chave e verifica claims temporais como exp. Sempre use verify em produção.

P: Como gerenciar a renovação de tokens com segurança? R: Emita um access token de curta duração (15–60 min) e um refresh token de longa duração (dias a semanas). Armazene refresh tokens no servidor para que possam ser revogados. Quando o access token expira, o cliente envia o refresh token a um endpoint dedicado para obter um novo access token.

P: Posso usar JWT tanto para autenticação quanto para autorização? R: Sim. Inclua claims de identidade (quem é o usuário) e claims de autorização (o que ele pode fazer, ex: roles, scope) no mesmo token. Mantenha o tamanho do payload razoável.

P: O que acontece se meu segredo JWT vazar? R: Um atacante pode forjar tokens válidos para qualquer usuário. Rotacione o segredo imediatamente (isso invalida todos os tokens existentes), investigue a fonte do vazamento e force todos os usuários a se reautenticarem.

P: Devo usar HS256 ou RS256? R: Use RS256 (ou ES256) quando múltiplos serviços verificam tokens ou quando o verificador não é totalmente confiável. Use HS256 apenas quando o mesmo serviço emite e verifica tokens dentro de um limite de implantação estritamente controlado.

P: Qual o tamanho máximo de um JWT? R: Mantenha JWTs abaixo de 4 KB para evitar limites de tamanho de cabeçalhos HTTP e problemas de desempenho. Não incorpore grandes estruturas de dados no payload; referencie-as por ID.