Glossário

O que é um JWT (JSON Web Token)? Como funcionam os tokens assinados e como usá-los com segurança

Um JWT é um token assinado pelo servidor para detectar adulteração. Como funciona e os riscos: não verificar a assinatura, aceitar alg:none e expor segredos.

Publicado 2026-06-12 Atualizado 2026-10-06 9 min de leitura
Nesta página

Um token assinado que um servidor te entrega depois do login: isso é um JWT. Veja como ele funciona e os pontos-chave para usá-lo com segurança (sem passos de ataque).

Como funciona (três partes)

Um JWT é header.payload.signature unidos por .. O header e o payload são apenas codificados em base64url (não criptografados); só a assinatura é feita com uma chave secreta (ou compartilhada).

1. header

metadados como o algoritmo de assinatura. qualquer um pode ler

2. payload

claims como id do usuário e expiração. qualquer um pode ler = sem segredos

3. signature

feita com uma chave. garante a ausência de adulteração

Um JWT tem três partes. Header e payload são 'apenas legíveis'; a assinatura fornece a garantia de autenticidade.

O ponto-chave é que o conteúdo é "apenas legível". Então o payload não é lugar para senhas ou dados pessoais. O valor de um JWT é que, ao verificar a assinatura, o servidor pode confirmar "eu emiti este token e ele não foi alterado".

Defesas para usá-lo com segurança

1

Sempre verifique a assinatura e fixe o alg (o mais importante)

Verifique a assinatura no servidor toda vez. Fixe o algoritmo de assinatura (alg) aceito no valor que você espera e rejeite alg:none (sem assinatura). Não confie cegamente no alg escrito no header do token.

A RFC de boas práticas para JWT (RFC 8725) determina que as bibliotecas DEVEM permitir que quem as chama especifique o conjunto de algoritmos suportados e NÃO DEVEM usar nenhum outro, e que todas as operações criptográficas do JWT devem ser validadas, rejeitando o JWT inteiro se qualquer uma delas falhar.

2

Bloqueie a troca de algoritmo, não só o alg:none

O abuso do alg não se limita a remover a assinatura. A RFC 8725 descreve como trocar RS256 por HS256 faz algumas bibliotecas tentarem validar a assinatura com HMAC-SHA256 usando a chave pública RSA como segredo compartilhado (confusão de algoritmo). A chave pública é, por definição, pública — então, se isso funcionar, um atacante consegue criar ele mesmo uma assinatura válida.

A defesa é a mesma: não confie no alg do header; fixe o algoritmo que o servidor espera. Decida primeiro o algoritmo e depois verifique, em vez de escolher a rotina de verificação a partir do material de chave que você recebeu.

3

Valide para quem é e até quando vale

Uma assinatura válida só diz que o token é genuíno. Se ele é destinado a você e ainda está válido é uma verificação separada.

A RFC 7519 diz que, para aud, se quem processa a claim não se identificar com um valor de 'aud' quando ela estiver presente, o JWT DEVE ser rejeitado, e que exp identifica o momento a partir do qual o JWT NÃO DEVE ser aceito para processamento (nbf funciona da mesma forma na outra ponta). A RFC 8725 acrescenta que a aplicação deve validar que as chaves usadas pertencem ao emissor. Um token emitido legitimamente para outro serviço sendo aceito pelo seu é exatamente o resultado de pular essas checagens.

4

Não coloque segredos no payload

Suponha que qualquer pessoa pode decodificar o conteúdo. Mantenha segredos — senhas, dados pessoais, chaves de API — fora dele. Inclua apenas claims que não sejam catastróficos se vistos, como identificadores e permissões.

5

Mantenha a expiração curta e tenha como revogar

Faça os tokens de acesso de curta duração. Uma expiração longa demais estende a janela de dano se um for roubado. Se você precisa de revogação, combine um token de acesso de curta duração com um refresh/sessão gerenciado pelo servidor.

6

Use uma chave forte e armazene-a onde não possa ser roubada

Faça a chave de assinatura forte, não a reutilize e armazene-a em algum lugar seguro no servidor. Proteja também o próprio token — evite que seja roubado via XSS, carregue-o num cookie com atributos seguros (→ cuidado com o roubo via XSS).

A visão deste site: um JWT não é um mecanismo de sessão para todo uso

Os JWTs são muitas vezes usados para "manter o estado de login", mas têm uma fraqueza: a revogação é difícil. Se a assinatura é válida e não expirou, o servidor basicamente confia nela, então fazer um logout ou uma invalidação ter efeito imediato é complicado.

Nossa postura é: não use um JWT como substituto de longa duração para uma sessão. Combine um token de acesso de curta duração com um refresh/sessão revogável no servidor, e você obtém tanto a vantagem do JWT (verificação barata) quanto a revogação fácil.

Atenção: "decodificou" não é "é válido"

Como o conteúdo é legível, qualquer pessoa pode colar um JWT num decodificador de JWT e inspecionar o header e o payload. Mas decodificar (ler o conteúdo) e verificar (confirmar a autenticidade) são coisas inteiramente diferentes. Conseguir decodificar não garante nada sobre a validade.

O que decide se um token é genuíno é sempre a verificação da assinatura no servidor. Ler o conteúdo para depuração é prático — apenas não confunda "consegui ler" com "é válido".

JWT vs. sessões no servidor (cookies)

Um JWT é apenas uma das formas de manter o estado de login, e ele se encaixa melhor que uma sessão no servidor em alguns casos e pior em outros.

ItemSessão no servidor (cookie)JWT
Onde fica o estadoNo servidor (BD ou memória); o cookie guarda só um IDDentro do token; o servidor só verifica a assinatura
Logout / suspensãoApagar no servidor tem efeito imediatoAceito até expirar, a menos que você implemente revogação à parte
Visibilidade do conteúdoSó um ID, nada para lerQualquer pessoa pode decodificar e ler
Melhor usoUm aplicativo web comum em um único domínioVários serviços ou APIs verificando o mesmo token

Para um aplicativo web que vive em um único domínio, uma sessão no servidor costuma bastar. Se você escolher JWT, emitir um token novo no login segue o mesmo princípio da defesa contra fixação de sessão.

Um caso real: uma biblioteca que não checava o algoritmo

A troca de algoritmo não é só teoria. A biblioteca de JWT para Node.js jsonwebtoken, muito usada, nas versões 4.2.1 e anteriores não checava corretamente o algoritmo indicado no header do token, o que permitia contornar a verificação (CVE-2015-9235, corrigida na 4.2.2). Um token que deveria ser verificado com chave pública podia ser assinado com um algoritmo de chave compartilhada (família HS) e ainda assim passar — exatamente a confusão de algoritmo descrita acima.

Duas lições:

  • Mantenha a biblioteca atualizada. Você pode checar suas dependências contra vulnerabilidades conhecidas colando um lockfile no scanner de vulnerabilidades de dependências
  • Não dependa dos padrões da biblioteca; declare explicitamente no seu código o algoritmo aceito

Como checar os seus próprios tokens

Cole um token emitido pelo seu próprio serviço no decodificador de JWT e observe os pontos abaixo. A decodificação roda no seu navegador e o token não é enviado a nenhum servidor. Mesmo assim, para um token de produção ativo, é sensato fazer logout depois para invalidá-lo.

  1. O alg do header é o que você espera (e não none)?
  2. Existe um exp, e a validade a partir do iat (momento de emissão) é adequada ao uso?
  3. aud e iss estão presentes e apontam para o seu serviço?
  4. O payload contém algo que você não gostaria que fosse visto — e-mails, telefones, chaves de API?

Cheque a verificação no servidor com testes em um ambiente de desenvolvimento. Um token com um caractere da assinatura alterado, um token com outro alg, um token expirado e um token destinado a outro serviço (aud errado) devem ser todos rejeitados — mantenha isso como teste automatizado.

Fontes (primárias)

  • IETF RFC 8725, "JSON Web Token Best Current Practices" (em inglês) — datatracker.ietf.org (fixar algoritmos, validar todas as operações criptográficas, confusão de algoritmo, chaves pertencentes ao emissor)
  • IETF RFC 7519, "JSON Web Token (JWT)" (em inglês) — datatracker.ietf.org (definições normativas de exp, nbf e aud)
  • GitHub Advisory Database, "Verification Bypass in jsonwebtoken" (CVE-2015-9235) (em inglês) — github.com/advisories (afeta a 4.2.1 e anteriores; corrigida na 4.2.2)
  • OWASP HTML5 Security Cheat Sheet (em inglês) — cheatsheetseries.owasp.org (não guardar identificadores de sessão no localStorage)

Leia a seguir

FAQ

QO conteúdo de um JWT é criptografado?
A

Não. O header e o payload de um JWT padrão são 'codificados' com base64url, não criptografados, então qualquer pessoa que tenha o token pode ler o conteúdo. Por isso, nunca coloque segredos como senhas ou dados pessoais no payload. O que um JWT protege não é a 'confidencialidade do conteúdo', mas o fato de que 'ele não foi adulterado' (integridade, via a assinatura).

QQual é a configuração mais perigosa de um JWT?
A

Não verificar a assinatura, ou aceitar 'alg:none' (sem assinatura). Permitir isso deixa um atacante passar um token forjado com conteúdo livremente reescrito. A defesa é sempre verificar a assinatura no servidor e fixar o algoritmo de assinatura (alg) aceito no valor que você espera.

QDecodificar e verificar são a mesma coisa?
A

Não. Decodificar apenas lê o conteúdo e qualquer pessoa pode fazê-lo (você pode checar com um decodificador de JWT). Verificar é o servidor confirmar, com uma chave secreta/pública, que a assinatura é válida, que o token não expirou e que o emissor/público estão corretos. 'Decodificou' não significa 'é um token válido' — a verificação no servidor decide a autenticidade.

QDevo usar JWT ou sessões (cookies)?
A

Para um aplicativo web comum em um único domínio, uma sessão no servidor com cookie costuma bastar, e o logout ou a suspensão de uma conta têm efeito imediato. Os JWTs se encaixam quando vários serviços ou APIs verificam o mesmo token, ou quando você recebe tokens de um provedor de identidade externo (OAuth/OpenID Connect). Se usar JWT, mantenha a expiração curta e combine-o com algo que o servidor possa revogar.

QPosso guardar um JWT no localStorage?
A

Não é recomendado. O localStorage é sempre legível por JavaScript, então uma única falha de XSS permite que um atacante roube o token. A OWASP também desaconselha guardar identificadores de sessão no localStorage. No navegador, levar o token num cookie com HttpOnly, Secure e SameSite é mais seguro; se usar cookie, adicione também proteção contra CSRF.

QO que é 'alg:none' em um JWT?
A

É um JWT cujo header define alg (o algoritmo de assinatura) como none, ou seja, sem assinatura. A especificação permite isso, mas um token usado para autenticação, como o de login, nunca deve aceitá-lo; caso contrário, qualquer pessoa pode criar um token com conteúdo reescrito. Evite isso fixando no servidor o algoritmo aceito no valor esperado (por exemplo, somente RS256).