O que é JWT e como ele funciona
JWT (JSON Web Token) é um padrão aberto definido pela RFC 7519 para representar claims de forma compacta, portátil e verificável. É a base de autenticação stateless em APIs REST, federação de identidade e autorização entre microsserviços.
Um JWT é composto por três partes separadas por pontos (.), cada uma codificada em Base64URL:
- Header — tipo do token (
JWT) e algoritmo de assinatura (alg), ex:{"alg":"RS256","typ":"JWT"} - Payload — conjunto de claims (afirmações), como
sub(subject),exp(expiração),iss(emissor),aud(audiência) e claims customizadas - Signature — assinatura digital gerada sobre Header + Payload usando a chave privada (RS256/ES256) ou segredo compartilhado (HS256)
O receptor verifica a assinatura com a chave pública correspondente (ou segredo compartilhado). Se válida, o conteúdo do payload é confiável. Importante: o payload não é cifrado — apenas assinado. Qualquer pessoa com acesso ao token pode decodificar e ler seu conteúdo.
Usos legítimos de JWT
JWT é adequado para:
- Autenticação stateless: o servidor não precisa armazenar estado de sessão — a identidade do usuário está no token, verificável com a chave pública
- Autorização entre microsserviços: um serviço de autenticação centralizado emite tokens que outros serviços validam localmente sem consultar um banco de dados central
- Federação e SSO: padrões como OpenID Connect (OIDC) usam JWT como ID Token para provar a identidade do usuário autenticado
- APIs consumidas por múltiplos clientes: mobile, SPA, CLIs e integrações B2B podem usar o mesmo mecanismo de autenticação
Vulnerabilidades clássicas e como funcionam
A maioria dos ataques contra JWT não explora falhas criptográficas brutas — explora implementações incorretas da validação. O OWASP API Security Top 10 lista falhas de autenticação como risco crítico em APIs. Abaixo, as vulnerabilidades mais comuns documentadas na literatura de segurança.
1. Ataque alg:none
A RFC 7519 define none como algoritmo válido para tokens não assinados. Bibliotecas que aceitam o campo alg diretamente do cabeçalho do token sem verificação permitem que um atacante troque o algoritmo para none, remova a assinatura e apresente um token forjado com qualquer payload. A correção exige que o servidor especifique o algoritmo aceito independentemente do que está no cabeçalho.
2. Confusão de algoritmo (RS256 → HS256)
Este é o ataque mais sofisticado e frequentemente subestimado. Quando um servidor aceita tanto RS256 quanto HS256, um atacante pode obter a chave pública RSA (muitas vezes exposta em /.well-known/jwks.json) e usá-la como segredo HMAC para assinar um token com HS256. O servidor, ao verificar, usa a mesma chave pública como segredo — e a assinatura é válida. O ataque foi documentado e demonstrado por PortSwigger em múltiplas CVEs de bibliotecas JWT populares.
3. Segredo HMAC fraco ou previsível
Quando HS256 é usado, a segurança depende inteiramente da entropia do segredo. Segredos como secret, password ou strings de desenvolvimento deixadas em produção são trivialmente quebráveis com ferramentas como hashcat ou jwt_tool. Pesquisas mostram que uma fração significativa de implementações em produção usa segredos inseguros.
4. Ausência de validação de claims
Bibliotecas JWT geralmente verificam apenas a assinatura por padrão. As claims exp (expiração), nbf (not before), iss (emissor) e aud (audiência) precisam ser validadas explicitamente. Um token expirado aceito pelo servidor, ou um token emitido para outro serviço aceito sem verificar aud, representa vulnerabilidade de autorização — documentada no OWASP Cheat Sheet Series para JWT.
5. Armazenamento em localStorage e XSS
Tokens armazenados no localStorage ou sessionStorage são acessíveis por qualquer JavaScript executado na página. Um único vetor XSS — seja em um campo de texto, um parâmetro de URL ou uma dependência npm comprometida — permite a exfiltração completa do token. Isso transforma uma vulnerabilidade de baixo impacto (XSS refletido) em uma de alto impacto (sequestro de sessão persistente).
6. Ausência de mecanismo de revogação
Por design stateless, um JWT válido não pode ser invalidado antes do vencimento sem infraestrutura adicional. Se um token é comprometido — por vazamento, XSS ou roubo de dispositivo — o atacante mantém acesso até a expiração. Em tokens com exp longo (24h, 7 dias ou sem expiração), o impacto é severo.
7. Dados sensíveis no payload
O payload é codificado em Base64URL, não cifrado. Senhas, CPFs, números de cartão ou dados de saúde presentes no payload ficam expostos a qualquer intermediário ou a quem tiver acesso ao token — incluindo logs de sistema que registram Authorization headers.
Tabela de vulnerabilidades e mitigações
| Vulnerabilidade | Impacto | Mitigação |
|---|---|---|
| alg:none aceito pelo servidor | Bypass de autenticação total | Fixar algoritmo no servidor; nunca confiar no campo alg do token |
| Confusão RS256/HS256 | Forja de token com chave pública | Aceitar apenas um algoritmo por endpoint; separar chaves por finalidade |
| Segredo HMAC fraco | Brute-force offline do token | Mínimo 256 bits gerados por CSPRNG; preferir algoritmos assimétricos |
| Sem validação de exp/aud/iss | Tokens expirados ou de outros serviços aceitos | Validar todas as claims explicitamente na configuração da biblioteca |
| Token no localStorage | Exfiltração por XSS | Cookie HttpOnly + SameSite=Strict + CSP rigorosa |
| Sem revogação | Token comprometido válido até expirar | Exp curto (5–15 min) + refresh token com rotação e denylist de JTI |
| Dados sensíveis no payload | Exposição de PII/dados financeiros | Apenas identificadores no payload; dados sensíveis exigem JWE (RFC 7516) |
| Sem rotação de chaves | Comprometimento permanente de chave privada | Rotação programada (ex: 90 dias); JWKS com suporte a múltiplas chaves ativas |
Boas práticas de implementação
Algoritmo e chaves
Use algoritmos assimétricos: RS256 (RSA-PKCS1-v1.5 + SHA-256), ES256 (ECDSA P-256) ou EdDSA com Ed25519. Algoritmos assimétricos eliminam a necessidade de compartilhar segredos entre serviços — cada serviço pode verificar tokens com a chave pública sem ter acesso à chave privada de emissão. Nunca use HS256 em arquiteturas onde múltiplos serviços precisam verificar tokens, pois exigiria distribuir o segredo a todos eles, ampliando a superfície de ataque.
Armazene chaves privadas em cofres de segredos com controle de acesso auditável. Rotacione chaves periodicamente e mantenha o endpoint JWKS atualizado com sobreposição de vigência para não invalidar tokens em circulação.
Claims obrigatórias
Configure sua biblioteca para validar explicitamente: exp (com tolerância máxima de clock skew de 60 segundos), iss (emissor esperado, fixo no servidor), aud (audiência do serviço que está validando) e jti (UUID único por token, para denylist). Claims de papel (roles, scope) devem ser validadas na camada de autorização, não apenas de autenticação.
Duração e rotação de tokens
Tokens de acesso devem expirar em 5 a 15 minutos. Refresh tokens, armazenados com hash no banco de dados, podem ter vida de dias ou semanas — mas com rotação obrigatória a cada uso. Ao detectar reuso de um refresh token já consumido, invalide imediatamente toda a família de tokens do usuário: isso indica comprometimento do refresh token e deve gerar alerta de segurança.
Armazenamento seguro no cliente
Tokens devem ser transmitidos e armazenados em cookies com os atributos HttpOnly (inacessível ao JavaScript), Secure (apenas HTTPS) e SameSite=Strict ou Lax (proteção contra CSRF). Em SPAs que precisam ler o token, uma alternativa é o padrão BFF (Backend for Frontend), onde o servidor gerencia cookies e expõe apenas um endpoint de verificação de sessão.
JWT versus sessão tradicional
A escolha entre JWT stateless e sessão server-side é uma decisão arquitetural com trade-offs relevantes, especialmente em contextos regulados como fintechs e healthtechs.
Sessão tradicional armazena o estado no servidor (banco ou Redis). O cliente guarda apenas um identificador opaco. Vantagens: revogação imediata, sem risco de dados no cliente, controle centralizado. Desvantagem: exige estado compartilhado entre instâncias do servidor (sticky session ou store distribuído).
JWT stateless carrega o estado no token. Vantagens: escalabilidade horizontal sem estado compartilhado, adequado para microsserviços e APIs públicas. Desvantagem: revogação é complexa, tokens comprometidos são válidos até expirar, e a superfície de ataque inclui a lógica de validação em cada serviço.
Para aplicações sujeitas ao Open Finance Brasil (Resolução BCB 32/2020) ou PCI DSS, a capacidade de revogação imediata de sessão é frequentemente um requisito — o que favorece sessão server-side ou JWT com denylist ativa e exp muito curto.
JWT em APIs de fintech e ambientes regulados
Em fintechs brasileiras sob regulação do Banco Central, o Open Finance Brasil adota o padrão FAPI 1.0 Advanced, que exige: tokens de acesso com exp máximo de 15 minutos, algoritmos assimétricos (PS256 ou ES256), validação de aud obrigatória e uso de PKCE no fluxo de autorização. A ausência de qualquer desses controles configura não conformidade auditável.
Em APIs de pagamento (PIX, TED, boleto), tokens com escopo inadequado ou sem validação de aud podem ser reutilizados entre endpoints — permitindo que um token emitido para consulta de saldo seja usado para iniciar uma transferência, se o servidor não verificar o escopo com granularidade suficiente.
Testes de penetração especializados em APIs financeiras devem sempre cobrir: replay de tokens, confusão de algoritmo, bypass de validação de claims e cenários de token leakage via logs e headers.
Ferramentas e referências
- RFC 7519 — JSON Web Token (JWT) — especificação normativa do padrão
- RFC 7516 — JSON Web Encryption (JWE) — para payload cifrado
- OWASP JWT Security Cheat Sheet — controles práticos por plataforma
- PortSwigger Web Security Academy — JWT Attacks — laboratórios práticos de ataque e defesa
- Auth0 — Critical Vulnerabilities in JWT Libraries — análise seminal do ataque alg:none e confusão de algoritmo
- OWASP API Security Top 10 — Broken Authentication — contexto de risco em APIs
Perguntas frequentes
O que é JWT e para que ele serve?
JWT (JSON Web Token) é um formato compacto e autocontido para transmitir informações entre partes como um objeto JSON assinado digitalmente. É definido pela RFC 7519 e amplamente usado para autenticação stateless em APIs REST, autorização de microsserviços e troca segura de claims entre sistemas. Um JWT válido garante que o payload não foi adulterado após a emissão — desde que a assinatura seja verificada corretamente.
Qual é a vulnerabilidade mais crítica em implementações de JWT?
O ataque de confusão de algoritmo é considerado o mais crítico. Ocorre quando o servidor aceita tokens assinados com HS256 usando a chave pública RS256 como segredo. Um atacante que obtém a chave pública (frequentemente exposta em /.well-known/jwks.json) pode forjar tokens válidos. A mitigação exige que o servidor especifique explicitamente o algoritmo aceito, sem confiar no campo alg do cabeçalho do token.
É seguro armazenar JWT no localStorage?
Não. O localStorage é acessível por qualquer JavaScript executado na página, tornando o token vulnerável a ataques XSS. Qualquer script injetado — inclusive por extensões de browser maliciosas ou dependências comprometidas — pode exfiltrar o token. A recomendação da OWASP é armazenar tokens de acesso em cookies HttpOnly e SameSite=Strict ou Lax, inacessíveis ao JavaScript e com proteção nativa contra CSRF.
Como funciona a revogação de JWT se o token é stateless?
Por design, JWT stateless não tem mecanismo nativo de revogação — o token é válido até expirar. Para revogar antes do vencimento, é necessário manter uma denylist (lista negra) no servidor com os JTI (JWT ID) invalidados, ou adotar tokens de acesso de vida curta (5–15 min) combinados com refresh tokens de vida longa armazenados com controle de versão no banco. O padrão de token rotation com invalidação do refresh anterior é o mais adotado em produção.
Dados sensíveis podem ser colocados no payload do JWT?
Não. O payload de um JWT é apenas codificado em Base64URL — não cifrado. Qualquer pessoa com acesso ao token pode decodificá-lo sem conhecer a chave. Isso significa que CPF, senha, número de cartão ou qualquer dado sensível jamais deve constar no payload. Para transmitir dados que precisam estar cifrados, o padrão correto é JWE (JSON Web Encryption), definido na RFC 7516.
JWT ou sessão tradicional: qual usar em uma fintech?
Depende do modelo de ameaças. Sessões tradicionais (server-side session ID em cookie) facilitam a revogação imediata e não expõem dados no cliente, sendo preferíveis quando o controle de sessão granular é prioritário. JWT é vantajoso em arquiteturas de microsserviços e APIs consumidas por múltiplos clientes, onde evitar consulta ao banco a cada requisição melhora escalabilidade. Fintechs com requisitos regulatórios (Open Finance, PCI DSS) tendem a combinar os dois: JWT de curta duração para a API e sessão server-side para o portal web.
Pentest de API e AppSec com a Decripte
A Decripte realiza testes de penetração especializados em APIs e aplicações web para empresas de todos os portes — do MEI ao enterprise com mais de 100.000 colaboradores. Nosso time cobre os principais vetores de ataque em JWT (confusão de algoritmo, bypass de validação, token leakage, replay) dentro de um escopo técnico rigoroso e com entrega de evidências acionáveis.
Acesse o plano gratuito de Gestão de Ameaças para um diagnóstico inicial da sua postura de segurança, ou explore nossos planos de AppSec e pentest de API para cobertura contínua.
