Entenda o que é um JWT (JSON Web Token), como suas três partes funcionam, onde é usado e as principais dicas de segurança para evitar erros comuns.

Um JWT (JSON Web Token) é uma string compacta e segura para URLs que representa um conjunto de informações (normalmente sobre um usuário ou sessão) de forma a poder ser passada entre sistemas. Você frequentemente o verá como um valor longo começando por algo como eyJ..., enviado em um cabeçalho HTTP como Authorization: Bearer <token>.
Logins tradicionais muitas vezes dependem de sessões no servidor: depois de fazer login, o servidor armazena dados de sessão e fornece ao navegador um cookie de ID de sessão. Cada requisição inclui esse cookie e o servidor consulta a sessão.
Com autenticação baseada em tokens, o servidor pode evitar manter estado de sessão para cada requisição do usuário. Em vez disso, o cliente guarda um token (como um JWT) e o inclui nas chamadas à API. Isso é popular em APIs porque:
Nuance importante: “sem estado” não significa “sem verificações no servidor”. Muitos sistemas reais ainda validam tokens contra o status do usuário, rotação de chaves ou mecanismos de revogação.
JWTs comumente carregam prova de autenticação (você está autenticado) e dicas básicas de autorização (roles, permissões, scopes)—mas seu servidor ainda deve aplicar as regras de autorização.
Você verá JWTs usados com frequência como tokens de acesso em:
Um JWT é uma string compacta feita de três partes, cada uma codificada em base64url e separadas por pontos:
header.payload.signature
Exemplo (redigido):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNzAwMDAwMDAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c…
O header descreve como o token foi criado—mais importante, o algoritmo de assinatura (por exemplo, HS256, RS256/ES256) e o tipo do token.
Campos comuns:
typ: frequentemente "JWT" (muitas vezes ignorado na prática)alg: o algoritmo de assinatura usadokid: identificador de chave para ajudar o verificador a selecionar a chave correta durante rotaçãoNota de segurança: não confie no header cegamente. Aplique uma allowlist de algoritmos que você realmente usa e não aceite alg: "none".
O payload contém “claims” (campos) sobre o usuário e o contexto do token: para quem é, quem o emitiu e quando expira.
Importante: JWTs não são criptografados por padrão. A codificação Base64URL torna o token seguro para URLs; ela não oculta os dados. Qualquer pessoa que obtenha o token pode decodificar header e payload.
Por isso evite colocar segredos (senhas, chaves de API) ou dados pessoais sensíveis dentro de um JWT.
A assinatura é criada assinando o header + payload com uma chave:
A assinatura fornece integridade: permite ao servidor verificar que o token não foi modificado e foi emitido por um assinador confiável. Ela não fornece confidencialidade.
Como um JWT inclui header e payload em cada requisição onde é enviado, tokens maiores significam mais largura de banda e overhead. Mantenha os claims enxutos e prefira identificadores a dados volumosos.
Claims geralmente caem em duas categorias: registrados (nomes padronizados) e customizados (campos do seu app).
iss (issuer): quem criou o tokensub (subject): quem é o assunto do token (frequentemente um ID de usuário)aud (audience): para quem o token é destinado (ex.: uma API específica)exp (expiration time): quando o token deve parar de ser aceitoiat (issued at): quando o token foi criadonbf (not before): o token não deve ser aceito antes desse momentoInclua apenas o que o serviço receptor realmente precisa para tomar uma decisão de autorização.
Bons exemplos:
user_id)Evite “claims de conveniência” que duplicam muitos dados de perfil. Eles incham o token, ficam rapidamente desatualizados e aumentam o impacto em caso de vazamento.
Como o payload é legível, não armazene:
Se precisar de informação sensível, armazene-a no servidor e coloque apenas uma referência (como um ID) no token—ou use um formato de token criptografado (JWE) quando apropriado.
Assinar não é criptografar.
Quando um JWT é emitido, o servidor assina o header + payload codificados. Quando o token é apresentado depois, o servidor recalcula a assinatura e a compara. Se alguém alterar mesmo um caractere (ex.: "role":"user" para "role":"admin"), a verificação falha e o token é rejeitado.
JWT é um formato de token. OAuth 2.0 e OpenID Connect (OIDC) são protocolos que descrevem como apps solicitam, emitem e usam tokens.
OAuth 2.0 trata principalmente de autorização: permitir que um app acesse uma API em nome de um usuário sem compartilhar a senha do usuário.
Access tokens são tipicamente de curta duração (minutos). Vidas curtas limitam o dano se um token vazar.
OIDC adiciona autenticação (quem é o usuário) em cima do OAuth 2.0 e introduz um ID token, que geralmente é um JWT.
Uma regra chave: não use um ID token para chamar uma API.
Se quiser mais contexto sobre fluxos práticos, veja /blog/jwt-authentication-flow.
Um fluxo típico se parece com isto:
O usuário faz login (email/senha, SSO, etc.). Se for bem-sucedido, o servidor cria um JWT (frequentemente um access token) com claims essenciais como subject e expiração.
O servidor assina o token e o retorna ao cliente (app web, app móvel ou outro serviço).
Para endpoints protegidos, o cliente inclui o JWT no cabeçalho Authorization:
Authorization: Bearer <JWT>
Antes de atender a requisição, a API normalmente checa:
exp (não expirado)iss (issuer esperado)aud (destinado a esta API)Se todas as checagens passarem, a API considera o usuário autenticado e aplica as regras de autorização (ex.: permissões ao nível de registro).
Como relógios de sistema variam, muitos sistemas permitem um pequeno clock skew ao validar claims baseados em tempo como exp (e às vezes nbf). Mantenha o skew pequeno para evitar estender a validade do token além do pretendido.
As escolhas de armazenamento mudam o que um atacante pode roubar e quão facilmente podem reproduzir um token.
Armazenamento em memória (frequentemente recomendado para SPAs) guarda o access token no estado JS. É limpo ao atualizar a página e reduz o risco de “pegar depois”, mas um bug XSS ainda pode lê-lo enquanto a página está ativa. Combine com tokens de curta duração e um fluxo de refresh.
localStorage/sessionStorage são fáceis, mas arriscados: qualquer vulnerabilidade XSS pode exfiltrar tokens do armazenamento web. Se usá-los, trate prevenção de XSS como imprescindível (CSP, escape de saída, higiene de dependências) e mantenha tokens de curta duração.
Cookies seguros (geralmente o padrão mais seguro para web) armazenam tokens em um cookie HttpOnly para que o JavaScript não possa lê-los—reduzindo o impacto do roubo via XSS. A troca é o risco de CSRF, já que os navegadores anexam cookies automaticamente.
Se usar cookies, configure:
HttpOnlySecure (apenas HTTPS)SameSite=Lax ou SameSite=Strict (alguns fluxos cross-site podem precisar de SameSite=None; Secure)Considere também tokens CSRF para requisições que mudam estado.
No iOS/Android, armazene tokens no armazenamento seguro da plataforma (Keychain / armazenamento com suporte a Keystore). Evite arquivos simples ou preferências. Se seu modelo de ameaça inclui dispositivos com root/jailbreak, assuma extração possível e dependa de tokens de curta duração e controles no servidor.
Limite o que um token pode fazer: use scopes/claims mínimos, mantenha tokens de acesso de curta duração e evite embutir dados sensíveis.
JWTs são convenientes, mas muitos incidentes surgem de erros previsíveis. Trate um JWT como dinheiro: quem o obtém normalmente pode gastá-lo.
Se um token dura dias ou semanas, um vazamento dá ao atacante essa janela inteira.
Prefira access tokens de curta duração (minutos) e os renove por um mecanismo mais seguro. Se precisar de “lembrar-me”, faça isso com refresh tokens e controles server-side.
Assinaturas válidas não são suficientes. Verifique iss e aud, e valide claims baseados em tempo como exp e nbf.
Decodificar não é verificar. Sempre valide a assinatura no servidor e aplique permissões server-side.
Evite colocar JWTs em query params. Eles podem acabar no histórico do navegador, logs de servidores, ferramentas de analytics e cabeçalhos Referer.
Use Authorization: Bearer ... em vez disso.
Assuma que chaves e tokens podem vazar. Rode chaves de assinatura, use kid para suportar rotação suave e tenha uma estratégia de revogação (expirações curtas + habilidade de desabilitar contas/sessões). Para orientação sobre armazenamento, veja /blog/where-to-store-jwts-safely.
JWTs são úteis, mas não são automaticamente a melhor escolha. A questão real é se você se beneficia de um token autocontido que pode ser verificado sem consultar o banco de dados em cada requisição.
Para apps web server-rendered onde invalidação direta importa, sessões server-side com cookies HttpOnly muitas vezes são a opção mais simples e segura.
Escolha JWT se você precisa de verificação sem estado entre serviços e pode manter tokens de curta duração.
Evite JWT se precisar de revogação instantânea, planeja armazenar dados sensíveis no token ou pode usar cookies de sessão sem atrito.
Verifique usando a chave correta e o algoritmo esperado. Rejeite assinaturas inválidas—sem exceções.
exp (expiração)Assegure que o token não expirou.
nbf (not before)Se presente, assegure que o token não está sendo usado antes do tempo.
aud (audience)Confirme que o token foi destinado à sua API/serviço.
iss (issuer)Confirme que o token veio do emissor esperado.
Valide o formato do token, imponha tamanho máximo e rejeite tipos de claims inesperados para reduzir bugs em casos de borda.
HS256 (chave simétrica): um segredo compartilhado assina e verifica.
RS256 / ES256 (chaves assimétricas): chave privada assina; chave pública verifica.
Regra prática: se mais de um sistema independente precisa verificar tokens (ou você não confia totalmente em cada verificador), prefira RS256/ES256.
iss, aud e um ID de usuário apenas se a política permitir).O JWT é criptografado?
Não por padrão. A maioria dos JWTs é assinada, não criptografada, o que significa que o conteúdo pode ser lido por quem tem o token. Use JWE ou mantenha dados sensíveis fora dos JWTs.
Posso revogar um JWT?
Não facilmente se você depender apenas de tokens autocontidos. Abordagens comuns incluem tokens de acesso de curta duração, listas de negação para eventos de alto risco, ou refresh tokens com rotação.
Qual deve ser a duração do exp?
O mais curta possível sem prejudicar a UX e a arquitetura. Muitas APIs usam minutos para access tokens, combinados com refresh tokens para sessões mais longas.
Se você está implementando autenticação JWT em uma nova API ou SPA, muito trabalho é repetitivo: configurar middleware, validar iss/aud/exp, ajustar flags de cookie e evitar que tokens apareçam em logs.
Com Koder.ai, você pode gerar código para um app web (React), serviços backend (Go + PostgreSQL) ou um app Flutter via um fluxo interativo—depois iterar em um modo de planejamento, usar snapshots e rollback enquanto refina a segurança, e exportar o código quando estiver pronto. É uma forma prática de acelerar a construção de fluxos de autenticação baseados em JWT mantendo controle sobre lógica de verificação, estratégia de rotação de chaves e configurações de deploy/hospedagem (incluindo domínios customizados).
Um JWT (JSON Web Token) é uma string compacta e segura para URLs que carrega "claims" (campos de dados) e pode ser verificada por um servidor. É comumente enviado em requisições de API via:
Authorization: Bearer <token>A ideia principal: o servidor pode validar a integridade do token (pela assinatura) sem precisar de um registro de sessão por usuário em cada requisição.
A autenticação por sessão normalmente armazena estado no servidor (um registro de sessão referenciado por um cookie/ID de sessão). Com autenticação baseada em JWT, o cliente apresenta um token assinado a cada requisição e a API o valida.
JWTs são populares para APIs e arquiteturas multi-serviço porque a verificação pode ser feita localmente, reduzindo a necessidade de armazenamento de sessão compartilhado.
“Sem estado” ainda pode incluir verificações no servidor, como listas de revogação, checagens de status do usuário ou rotação de chaves.
Um JWT tem três partes codificadas em Base64URL separadas por pontos:
header.payload.signatureO header descreve como foi assinado, o payload contém claims (como sub, exp, aud) e a assinatura permite ao servidor detectar adulterações.
Não. JWTs padrão geralmente são assinados, não criptografados.
Se precisar de confidencialidade, use JWE (tokens criptografados) ou mantenha dados sensíveis no servidor e coloque apenas um identificador no JWT.
A assinatura permite verificar que o token não foi alterado e foi gerado por quem possui a chave de assinatura.
Ela não garante:
exp.Trate o token como uma credencial: se vazar, normalmente pode ser reutilizado até expirar.
alg informa qual algoritmo foi usado (por exemplo, HS256 vs RS256). kid é um identificador de chave que ajuda a selecionar a chave certa durante rotação.
Regras de segurança:
Comece com claims registrados padrão e mantenha claims customizados ao mínimo.
Claims comuns:
JWT é um formato de token; OAuth 2.0 e OpenID Connect são protocolos.
Mapeamento típico:
Para apps web, opções comuns:
localStorage/sessionStorage: conveniente, mas qualquer XSS pode exfiltrar tokens. Se usar, trate prevenção de XSS como obrigatória (CSP, escape de saída, higiene de dependências) e mantenha tokens curtos.No mínimo, valide:
exp (não expirado)iss (issuer esperado)aud (destinado à sua API)nbf (se presente)Guardrails práticos:
alg: "none"kid não confiável cause buscas inseguras por chaves.iss (issuer)sub (subject / identificador do usuário)aud (audience / API alvo)exp (expiração)iat (emitido em)nbf (não antes)Evite incluir segredos ou dados pessoais sensíveis no payload, pois eles ficam legíveis se o token for exposto.
Importante: não use um ID token para chamar uma API só porque ele “parece” um JWT de acesso.
Se usar cookies, configure:
HttpOnlySecure (apenas HTTPS)SameSite=Lax ou SameSite=Strict (alguns fluxos cross-site podem precisar de SameSite=None; Secure)Considere tokens anti-CSRF para requisições que mudam estado.