Developer Tools

JWT Tokens Explicados: Estrutura, Segurança e Erros Comuns

Entenda como os JSON Web Tokens funcionam, o que contém neles e as armadilhas de segurança que pegam desenvolvedores desprevenidos em produção.

8 min de leitura

Cadeado de segurança em uma placa de circuito

JSON Web Tokens (JWTs) estão em todo lugar — eles alimentam a autenticação em SPAs, aplicativos móveis e arquiteturas de microsserviços no mundo inteiro. Mesmo assim, são um dos conceitos de segurança mais mal compreendidos no desenvolvimento web. Implementá-los de forma errada pode resultar em bypass de autenticação, escalonamento de privilégios ou comprometimento total de contas.

O que é um JWT?

Um JWT é uma string compacta e segura para URLs que codifica um conjunto de claims — afirmações sobre um usuário ou sessão. Ele tem esta aparência:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

São três segmentos codificados em Base64URL separados por pontos:

  1. Header — algoritmo e tipo do token
  2. Payload — os claims (dados do usuário)
  3. Signature — prova criptográfica de integridade

Cole qualquer JWT no nosso JWT Decoder para inspecionar as três partes instantaneamente, sem precisar de nenhum servidor externo.

Anatomia de um JWT

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

alg especifica o algoritmo de assinatura. Valores comuns:

  • HS256 — HMAC com SHA-256 (simétrico, segredo único)
  • RS256 — RSA com SHA-256 (assimétrico, chave pública/privada)
  • ES256 — ECDSA com SHA-256 (assimétrico, chaves menores)

Payload

{
  "sub": "user_abc123",
  "email": "alice@example.com",
  "role": "admin",
  "iat": 1711670400,
  "exp": 1711756800
}

Claims registrados padrão:

Claim Significado
sub Subject (sobre quem é o token)
iss Issuer (quem criou o token)
aud Audience (quem deve aceitá-lo)
exp Tempo de expiração (timestamp Unix)
iat Emitido em (timestamp Unix)
nbf Not before (não aceitar antes deste momento)

Signature

Para HS256:

HMAC-SHA256(base64url(header) + "." + base64url(payload), secret)

A assinatura prova que o token não foi adulterado. O payload NÃO é criptografado — ele apenas é codificado. Qualquer pessoa pode lê-lo.

Nunca armazene dados sensíveis como senhas ou números de cartão de crédito no payload de um JWT.

HS256 vs. RS256: qual escolher?

HS256 usa um único segredo compartilhado. Todo serviço que precisa verificar tokens deve ter o mesmo segredo. Simples para aplicações monolíticas, mas perigoso em arquiteturas com múltiplos serviços — se qualquer serviço for comprometido, um invasor pode forjar tokens.

RS256 usa chaves assimétricas. O servidor de autenticação assina com uma chave privada; todos os outros serviços verificam com a chave pública. Comprometer um serviço consumidor não dá ao invasor a capacidade de forjar tokens. Prefira RS256 para qualquer sistema com múltiplos serviços.

A vulnerabilidade alg: none

Um dos ataques JWT mais famosos. Algumas bibliotecas mais antigas aceitavam um token com "alg": "none" e sem assinatura — tratando-o como válido. Um invasor poderia criar:

{ "alg": "none" }

com qualquer payload e bypassar a autenticação completamente.

Correção: Sempre especifique explicitamente os algoritmos permitidos na sua biblioteca JWT. Nunca aceite none.

// ❌ Perigoso
jwt.verify(token, secret);

// ✅ Seguro — aceita apenas HS256
jwt.verify(token, secret, { algorithms: ["HS256"] });

Ataque de confusão de algoritmo

Outra vulnerabilidade crítica: se sua biblioteca detecta automaticamente o algoritmo a partir do header, um invasor pode alterar RS256 para HS256 e assinar o token usando a chave pública como segredo HMAC (que, por definição, é pública).

Correção: Sempre defina o algoritmo esperado no código. Nunca confie no header alg.

Armazenamento de tokens: onde guardar JWTs

Armazenamento Risco de XSS Risco de CSRF Observações
localStorage Alto Nenhum Acessível a qualquer JS na página
sessionStorage Alto Nenhum Limpo ao fechar a aba
Cookie HTTP-only Nenhum Médio Melhor para apps web; use SameSite=Strict
Memória (variável) Baixo Nenhum Perdido ao atualizar; para SPAs

Para aplicações web, cookies HTTP-only com SameSite=Strict é a opção mais segura. Para aplicativos nativos, APIs de armazenamento seguro (Keychain, Keystore) são as mais indicadas.

Expiração e refresh tokens

Tokens de acesso de curta duração (5–15 minutos) combinados com refresh tokens de longa duração é o padrão mais adotado:

  1. Usuário faz login → servidor emite access token (15 min) + refresh token (7 dias, armazenado no BD)
  2. O cliente usa o access token para chamadas de API
  3. Quando o access token expira, o cliente envia o refresh token → recebe um novo access token
  4. No logout, invalide o refresh token no banco de dados

Isso limita o período de exposição caso um access token seja roubado.

Revogando JWTs

JWTs são stateless — uma vez emitidos, são válidos até a expiração. Isso é uma troca. Opções para revogar antes do prazo:

  • Blocklist — armazene valores JTI (JWT ID) invalidados no Redis. Verifique a cada requisição.
  • Expiração curta — tokens de 5 minutos limitam o raio de impacto.
  • Rotação de refresh token — detecte reutilização de um token rotacionado como sinal de roubo.

Depurando com o JWT Decoder

Ao depurar problemas de autenticação, use nosso JWT Decoder para:

  • Inspecionar o payload completo sem escrever código
  • Verificar timestamps de expiração em formato legível
  • Confirmar o algoritmo sendo utilizado
  • Identificar claims inesperados ou ausentes

Toda a decodificação acontece localmente no seu navegador — os tokens nunca saem da sua máquina.

Checklist de segurança para JWT

  • Use RS256 ou ES256 para arquiteturas com múltiplos serviços
  • Especifique explicitamente os algoritmos permitidos na sua biblioteca
  • Valide os claims exp, iss e aud em cada requisição
  • Armazene tokens em cookies HTTP-only para apps web
  • Use tempos de vida curtos para access tokens (15 min ou menos)
  • Implemente rotação de refresh token com detecção de reutilização
  • Nunca coloque dados sensíveis no payload
  • Use HTTPS em todo lugar — um token em texto plano equivale a não ter autenticação

JWTs são poderosos e convenientes, mas são tão seguros quanto sua implementação. Entenda a estrutura, conheça os ataques e sua camada de autenticação será sólida.