JWT explicado: como funciona a autenticação com token e os erros mais comuns
JWT (JSON Web Token) é um formato de token muito usado para autenticação em APIs. Depois que o usuário faz login, o servidor entrega um token assinado; nas próximas requisições, o cliente envia esse token e o servidor confere a assinatura para saber quem está chamando, sem precisar consultar uma sessão guardada. É simples de usar, mas cheio de detalhes que, quando ignorados, abrem falhas de segurança.
A estrutura de um JWT
Um JWT tem três partes separadas por pontos:
xxxxx.yyyyy.zzzzz
cabeçalho.payload.assinatura
- Cabeçalho (header): o tipo do token e o algoritmo de assinatura, como
HS256ouRS256. - Payload: as informações (claims), como o identificador do usuário (
sub), a data de expiração (exp), a data de emissão (iat) e perfis de acesso. - Assinatura: calculada a partir do cabeçalho, do payload e de uma chave secreta ou privada.
Exemplo de payload decodificado:
{
"sub": "1234",
"nome": "Ana",
"roles": ["cliente"],
"iat": 1793635200,
"exp": 1793636100
}
O ponto mais importante: JWT não é criptografado
As duas primeiras partes são apenas codificadas em Base64URL. Qualquer pessoa com o token consegue ler o payload. A assinatura garante que o conteúdo não foi alterado, não que ele é secreto. Por isso:
- nunca coloque senhas, dados sensíveis ou informações pessoais desnecessárias no payload;
- guarde apenas o necessário: identificador do usuário, perfis e expiração.
Como a validação funciona
Ao receber um token, o servidor deve:
- Verificar a assinatura com a chave correta.
- Conferir que o algoritmo é o esperado (não aceitar qualquer algoritmo informado no cabeçalho).
- Verificar a expiração (
exp) e, se usados, o emissor (iss) e o público (aud). - Só então confiar nas informações do payload.
Use bibliotecas consolidadas para isso, como o suporte a OAuth2 Resource Server do Spring Security, e nunca implemente a verificação manualmente.
HS256 ou RS256?
- HS256 usa uma única chave secreta compartilhada para assinar e verificar. Simples, mas todo serviço que verifica precisa conhecer o segredo, e quem conhece o segredo também consegue criar tokens.
- RS256 (ou ES256) usa um par de chaves: a privada assina, a pública verifica. Ideal quando vários serviços validam tokens emitidos por um único servidor de autenticação.
Com HS256, use uma chave longa e aleatória, guardada fora do código. Veja variáveis de ambiente e segredos.
Access token e refresh token
Um JWT não pode ser revogado facilmente antes de expirar, porque o servidor não guarda estado. A solução comum é usar dois tokens:
- Access token: JWT de vida curta, por exemplo 5 a 15 minutos, enviado em cada requisição.
- Refresh token: de vida mais longa, usado apenas para obter um novo access token. Ele fica guardado no servidor (ou registrado), o que permite revogá-lo no logout ou em caso de suspeita.
Assim, um access token roubado tem utilidade limitada no tempo, e o acesso pode ser cortado revogando o refresh token. Uma boa prática adicional é a rotação: cada uso do refresh token gera um novo e invalida o anterior.
Onde guardar o token no navegador
Esse é um dos debates mais comuns:
| Opção | Risco principal | Observação |
|---|---|---|
| localStorage | Qualquer script na página pode ler (XSS) | Simples, mas um XSS expõe o token |
| Memória da aplicação (variável JavaScript) | Perde-se ao recarregar a página | Combine com refresh token em cookie |
| Cookie HttpOnly, Secure, SameSite | Exige proteção contra CSRF | O JavaScript não consegue ler o cookie |
Uma abordagem bastante adotada em SPAs: access token na memória e refresh token em cookie HttpOnly, Secure e com SameSite adequado, junto com proteção CSRF no endpoint de renovação. Se a sua aplicação usa cookies e recebe erros 403 em POST, o problema provavelmente é CSRF; veja o caso real em Spring Security 403 em POST com React.
Enviando o token
O padrão é o cabeçalho Authorization:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Se o front-end e a API estão em domínios diferentes, configure o CORS corretamente. Veja CORS: o que é e como resolver os erros.
Erros comuns
- Aceitar o algoritmo "none" ou deixar o cabeçalho escolher o algoritmo. Fixe o algoritmo esperado no servidor.
- Segredo fraco ou no código-fonte. Um segredo vazado no GitHub permite que qualquer pessoa crie tokens válidos.
- Tokens que nunca expiram.
- Dados sensíveis no payload.
- Logar o token completo nos logs da aplicação. Veja logs em produção.
- Confiar nos perfis do token para tudo quando as permissões mudam com frequência. Para mudanças imediatas, consulte o estado atual no servidor.
- Não usar HTTPS. Sem HTTPS, o token pode ser interceptado.
JWT é sempre a melhor opção?
Não. Para aplicações web tradicionais, em que o mesmo servidor entrega as páginas e a API, sessões com cookie são mais simples e fáceis de revogar. JWT faz mais sentido em APIs consumidas por vários clientes (web, aplicativo móvel, outros serviços) e em arquiteturas com vários serviços. Para entender a base, veja o que é uma API REST e códigos de status HTTP, especialmente a diferença entre 401 e 403.
Na prática da PruPru
Escolher entre JWT e sessão com cookie muda o que você precisa proteger. Num sistema com Spring Boot 3 e React feito pela PruPru, a autenticação usava sessão com cookie, e por isso a proteção CSRF era obrigatória. Foi ela que fez todo POST, PUT e DELETE voltar 403 depois da atualização para o Spring Security 6. Com JWT enviado no cabeçalho Authorization, esse risco específico some, mas aparecem outros, como guardar o token com segurança no navegador. O caso completo está em Spring Security retornando 403 em POST com React.
Sistemas sob medida
A PruPru desenvolve APIs, sistemas web e integrações com as mesmas práticas descritas neste guia. Se a sua empresa precisa de software bem construído, conheça os serviços.
Ver serviços →Perguntas frequentes
JWT é criptografado?
Não, na forma mais comum (JWS). O cabeçalho e o payload são apenas codificados e qualquer pessoa pode lê-los. A assinatura garante a integridade. Existe o JWE, que criptografa o conteúdo, mas é menos usado.
Como fazer logout com JWT?
No cliente, descarte o access token. No servidor, revogue o refresh token. Como o access token tem vida curta, ele expira em poucos minutos. Para revogação imediata, é preciso manter uma lista de tokens bloqueados.
Qual o tempo de expiração ideal para um access token?
Em geral, entre 5 e 15 minutos, combinado com um refresh token de vida mais longa. O equilíbrio depende do risco da aplicação e da experiência desejada.
Posso guardar o JWT no localStorage?
Pode, mas qualquer vulnerabilidade de XSS permite que um script malicioso leia o token. Muitas aplicações preferem manter o access token em memória e o refresh token em cookie HttpOnly.