Um JSON Web Token é um formato compacto para transportar declarações entre sistemas. A forma mais conhecida possui três segmentos separados por pontos: header, payload e signature. Header e payload são JSON representado com Base64URL. A assinatura permite verificar que o conteúdo não foi alterado. Essa estrutura facilita APIs distribuídas, mas não transforma JWT em uma solução completa de autenticação ou autorização.

O header descreve a proteção

O header normalmente informa algoritmo e tipo do token. O verificador não deve confiar cegamente nessa escolha. A aplicação precisa configurar uma lista fechada de algoritmos permitidos para cada issuer e usar a chave correta.

Falhas históricas aceitaram none ou confundiram HMAC com algoritmos assimétricos. A primeira etapa de segurança é decidir a política fora do token.

O payload contém claims legíveis

Um JWT assinado não é criptografado. Quem possui a string consegue decodificar claims como subject, issuer, audience e expiration. Por isso, senhas, segredos e dados pessoais desnecessários não deveriam estar no payload.

A assinatura protege integridade, não confidencialidade. Se o conteúdo precisa ser secreto, use criptografia adequada ou mantenha a informação no servidor.

A assinatura conecta conteúdo e chave

O emissor assina a representação exata de header e payload. O consumidor verifica com a chave esperada. Qualquer alteração em um claim invalida a assinatura. Vários serviços podem confiar no mesmo emissor sem compartilhar uma sessão central.

Com HMAC, emissor e verificadores conhecem o mesmo segredo e todos podem assinar. Com RSA ou ECDSA, apenas a private key assina e public keys verificam. A escolha altera o modelo de confiança.

Claims registrados reduzem ambiguidade

iss identifica o emissor, sub o sujeito, aud o público, exp a expiração e nbf o início de validade. Verificar apenas a assinatura ignora metade do contrato.

Um token válido para outro serviço não deve funcionar aqui. Um token expirado não deve ser aceito só porque os bytes foram assinados corretamente.

Expiração limita o dano

Access tokens curtos reduzem a janela de abuso após roubo. Tokens longos se aproximam de senhas portáteis. Como JWT costuma ser stateless, revogação imediata exige blacklist, token version, introspection ou outro estado.

Muitos sistemas combinam access token curto e refresh token controlado. O refresh pode ser revogado e emitir novos access tokens conforme a sessão longa.

Clock skew precisa de regra

Servidores podem discordar por alguns segundos. Uma tolerância pequena evita rejeições legítimas de exp e nbf; uma tolerância grande prolonga a validade real. Todos os serviços deveriam aplicar a mesma política.

Logs precisam distinguir token expirado, ainda não válido, issuer incorreto, audience errada e assinatura inválida. Cada causa aponta para um problema diferente.

Onde o token é guardado muda o risco

localStorage é acessível ao JavaScript e vulnerável a roubo em caso de XSS. Cookie HttpOnly reduz esse acesso, mas introduz considerações de CSRF, SameSite e envio automático. Aplicativos móveis possuem mecanismos próprios de armazenamento seguro.

Não existe local perfeito. A decisão depende do cliente e do threat model, sempre acompanhada de HTTPS e redução do conteúdo.

Claims de autorização envelhecem

Permissões dentro do token permanecem até expiração. Se um usuário perde acesso a um projeto, o claim antigo pode continuar válido. Para ações sensíveis, o serviço pode precisar consultar estado atual ou usar tokens muito curtos.

Scopes devem ser específicos. Um booleano amplo como admin tende a acumular responsabilidades difíceis de auditar.

Tipos de token não devem ser intercambiáveis

Um ID token emitido para informar identidade a um cliente não deveria ser aceito como access token por uma API. Refresh tokens também possuem finalidade própria. Audience, issuer, typ e claims esperados ajudam a impedir token type confusion.

Endpoints devem declarar quais tipos aceitam e usar validadores separados quando as políticas diferem. Um parser genérico para qualquer JWT amplia a superfície de erro.

Descoberta de chaves precisa de confiança

Em sistemas assimétricos, verificadores podem obter public keys por JWKS. A URL e o issuer devem ser configurados, não escolhidos pelo token. Cache, expiração e rotação precisam ser tratados sem aceitar fontes arbitrárias.

Durante indisponibilidade do endpoint de chaves, o serviço precisa de uma política: usar cache ainda válido, falhar fechado e alertar. Buscar qualquer chave dinamicamente em toda requisição cria dependência e risco.

Decodificar não significa confiar

Ferramentas de debug mostram o payload sem validar segurança. A aplicação precisa verificar algoritmo, assinatura, issuer, audience, tempo e permissões. O token afirma algo; a política decide se a afirmação vale nesta requisição.

Um jti pode ajudar a correlacionar emissão e revogação sem registrar o token completo. Observabilidade deve guardar contexto, não credenciais.

JWT é um documento assinado, não uma sessão mágica

Ele funciona bem quando múltiplos serviços precisam verificar claims compactos. Funciona mal quando a arquitetura exige revogação imediata, dados sempre atuais e nenhuma estratégia adicional.

Testes de contrato devem usar tokens válidos, expirados, emitidos para outro audience, com algoritmo inesperado e com chave rotacionada. Esses casos provam a política melhor que um único exemplo feliz.

Com chaves protegidas, claims mínimos, expiração curta e validação completa, JWT é uma ferramenta útil. Sem essas regras, a string compacta apenas esconde decisões incompletas.