JSON Web Tokens
Um token opaco exige uma consulta: a string não significa nada, então o servidor precisa perguntar ao seu próprio armazenamento a quem ela pertence.
Tire a consulta e alguma coisa precisa substituí-la. Um JSON Web Token, ou JWT, faz isso colocando a resposta dentro do próprio token.
Três partes, uma string separada por pontos
Um JWT parece um amontoado de caracteres aleatórios, mas tem uma estrutura rígida. Três partes, unidas por pontos:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjQ4MjEsInJvbGUiOiJ0ZWFjaGVyIn0.4pcPyMD09olPSyXnrXCjTwXyr4BsezdI1AVTmud2fU4
└────────── header ──────────┘ └────────── payload ─────────┘ └────────── signature ──────────┘- Header. Qual algoritmo assinou o token e que se trata de um JWT.
- Payload. As informações de identidade, chamadas de claims: quem é o usuário, qual função ele exerce, quando o token expira, quem o emitiu.
- Signature. Um carimbo criptográfico que comprova que nada foi alterado.
O servidor o monta pegando o header e o payload, combinando-os com um segredo que só ele conhece, e produzindo a signature. As três partes são então codificadas e unidas.
Qualquer pessoa pode ler um JWT. Só quem tem o segredo consegue criar um que o servidor vá aceitar.
É isso que o torna confiável sem precisar de uma consulta, e é essa a ideia central resumida em uma frase.
Ou seja, o selo não esconde a carta. Ele prova quem a fechou, e que ninguém a abriu depois disso.
O fluxo, e o que mudou
- O usuário faz login com um nome de usuário e senha.
- O servidor os verifica.
- Em caso de sucesso, o servidor cria um JWT e o assina.
- O token vai para o cliente, que o armazena.
- Toda requisição seguinte o carrega no header
Authorization, exatamente como um token opaco faria. - O servidor verifica a signature e lê os claims. Sem consulta, sem armazenamento.
O passo seis é o único que difere dos tokens opacos do tipo bearer, e isso muda completamente o modelo:
| Token opaco bearer | JWT | |
|---|---|---|
| Conteúdo | Nada, uma string aleatória | Claims codificados: id do usuário, função, expiração |
| Para identificar o usuário | Consultar | Verificar a signature, ler os claims |
| Armazenamento no servidor | Uma pequena tabela token-usuário | Nenhum |
| Onde a identidade fica | No servidor | Dentro do token |
Um token opaco aponta para a identidade mantida no servidor. Um JWT contém essa identidade.
Fazer uma consulta significa que o servidor pode verificar a resposta mais atual. Ler o token significa que o servidor recebe a resposta que era verdadeira no momento em que o token foi criado.
Quatro formas de dar errado
Um JWT ainda é um token bearer, então toda armadilha dos tokens opacos continua valendo: roube-o e você vira o usuário. Ser autocontido acrescenta mais quatro.
| O que dá errado | Por que isso importa | A correção | |
|---|---|---|---|
| 1 | Presumir que está criptografado | Ele está codificado, não criptografado. Quem quer que o tenha em mãos pode ler o payload. Divulgação de informação no STRIDE, exposição de dados sensíveis no OWASP | Não coloque no payload nada que você não escreveria em um cartão-postal |
| 2 | Um segredo fraco ou vazado | Adivinhar ou roubar o segredo permite que um atacante assine seus próprios tokens, incluindo um que diga admin. Elevação de privilégio | Um segredo longo e aleatório, carregado do ambiente, nunca versionado |
| 3 | Um payload sobrecarregado | Tokens grandes significam headers grandes em toda requisição: requisições lentas, proxies insatisfeitos, logs inchados. E tudo que está ali vaza se o token vazar | Só o que o servidor precisa em toda requisição |
| 4 | Sem expiração | Você não consegue revogar um JWT, então sem uma expiração ele funciona para sempre. Falha de autenticação | Sempre defina uma, e mantenha-a curta |
A armadilha 2 é a que transforma um pequeno erro em um comprometimento total. Um id de sessão vazado compromete uma conta; um segredo de assinatura vazado compromete todas as contas, inclusive as que ainda nem existem.
Mas não é embaralhado. Está escrito em um alfabeto que não é amigável para leitura, e qualquer decodificador o transforma de volta em texto simples na hora.
Mão na massa
Uma auditoria de segurança stateless, quatro cenários.
// 1. Um registro na tabela de consulta de tokens
const tokenTable = [
{ token: 'a91f...', userId: 4821, expires: '3000-01-01T00:00:00Z' },
]
// 2. Chamada em toda requisição
function authenticate(token) {
const record = tokenTable.find((r) => r.token === token)
return record ?? null
}
// 3. O payload que vai dentro de um JWT
{ id: 4821, name: 'Mara', admin: false, streetAddress: 'Rua Augusta, 1200',
phone: '+55 11 91234-5678', tabSwitches: 14, windowResizes: 3 }
// 4. Configuração do servidor usada ao emitir JWTs
const config = { secret: 'secret123', algorithm: 'HS256' }Compare suas respostas
| # | Armadilha | Correção |
|---|---|---|
| 1 | Token de vida longa. Expira no ano 3000, quase certamente um erro de digitação, e continua sendo uma credencial válida por um milênio | Uma expiração de 30 minutos |
| 2 | Sem revogação. A função encontra o registro e o retorna sem nunca olhar para expires, então um token expirado autentica normalmente | Compare expires com o momento atual, retorne null se já passou, e aproveite para excluir a linha |
| 3 | Payload sobrecarregado, e divulgação de informação. Um endereço e um número de telefone ficam em algo que qualquer portador pode ler, junto com dados analíticos que o servidor nunca precisa | id, name e admin, nada além disso |
| 4 | Segredo fraco, e sem expiração. secret123 é adivinhável e está fixo no código, ou seja, está no repositório | Um segredo longo e aleatório vindo de uma variável de ambiente, além de um claim de expiração |
O cenário 2 é o que se esconde melhor. A função parece correta: ela realmente encontra o token e realmente retorna null para um que não existe. Armazenar uma expiração e nunca checá-la equivale a não ter expiração nenhuma.
Para onde isso vai a seguir
Dois modelos stateless, um trocando uma consulta pela revogação e o outro trocando a revogação pela escala. Nos dois, sua aplicação continua responsável pelas senhas, pelas redefinições e por todo o aparato de provar quem alguém é.
OAuth e identidade delegada questiona se você sequer quer essa responsabilidade.

