Como Segurar Tokens JWT: Guia de Melhores Práticas
Tokens JSON Web (JWTs) tornaram-se o padrão da indústria para autenticação sem estado. Eles permitem que servidores verifiquem a identidade de um usuário sem armazenar dados de sessão no próprio servidor. No entanto, essa natureza sem estado introduz riscos de segurança específicos se não implementados corretamente. Neste guia, exploraremos como proteger adequadamente os tokens JWT para proteger dados do usuário e manter a integridade do aplicativo.
Entendendo a Estrutura do JWT
Antes de mergulhar nas medidas de segurança, é crucial entender as três partes de um JWT: o Cabeçalho, a Carga Útil e a Assinatura.
- Cabeçalho: Contém o algoritmo usado para assinar o token (ex: HS256, RS256).
- Carga Útil: Contém as declarações (dados sobre o usuário, como ID e função).
- Assinatura: Garante que o token não tenha sido alterado.
Como a carga útil é codificada em base64, ela é legível para qualquer pessoa que intercepte o token. Por isso, medidas de segurança como HTTPS e validação de assinatura são não negociáveis.
1. Sempre Use HTTPS
A etapa mais fundamental na segurança de qualquer token é garantir que ele seja transmitido por um canal seguro. Se um JWT for enviado por HTTP, um atacante na rede pode interceptar e ler a carga útil do token, potencialmente extraindo informações sensíveis do usuário.
BBVA enfatiza que o uso de HTTPS é obrigatório para prevenir ataques de intermediário (man-in-the-middle). Essa criptografia garante que o token permaneça confidencial desde o momento em que sai do cliente até o momento em que chega no servidor.
2. Proteja seus Segredos de Assinatura
A assinatura é a única parte do JWT que prova que o token é autêntico. Para gerar uma assinatura válida, você precisa de uma chave secreta (para algoritmos simétricos) ou uma chave privada (para algoritmos assimétricos).
Não Codifique Segredos
Um dos erros mais comuns que os desenvolvedores cometem é codificar a chave secreta diretamente no código-fonte. Se seu código for enviado para um repositório público (como GitHub), o segredo fica exposto. A H2S Media recomenda contra essa prática, sugerindo em vez disso o uso de variáveis de ambiente para armazenar segredos. Isso mantém dados sensíveis separados da lógica do seu aplicativo e previne exposição acidental.
Rotacione Segredos Regularmente
Mesmo que seus segredos sejam armazenados com segurança, eles devem ser rotacionados periodicamente. Se um segredo for comprometido, um atacante pode forjar tokens indefinidamente. A rotação regular limita a janela de oportunidade para um atacante.
3. Escolha o Mecanismo de Armazenamento Adequado
Onde você armazena o JWT no lado do cliente é uma decisão de segurança crítica. As duas opções principais são LocalStorage e Cookies HttpOnly.
Os Riscos do LocalStorage
Armazenar JWTs em localStorage os torna acessíveis a qualquer JavaScript executado na página. Se o seu aplicativo tiver uma vulnerabilidade de Cross-Site Scripting (XSS), um atacante pode facilmente roubar o token e se passar pelo usuário. MakeUseOf destaca que, embora o localStorage seja conveniente, ele é vulnerável a ataques XSS.
A Segurança dos Cookies HttpOnly
Cookies HttpOnly não são acessíveis via JavaScript. Isso os torna imunes a ataques XSS que tentam roubar o token. Para máxima segurança, especialmente em aplicativos que lidam com dados sensíveis, armazenar o JWT em um cookie HttpOnly é a abordagem recomendada. Esse método também ajuda a mitigar ataques de Cross-Site Request Forgery (CSRF) se combinado com atributos SameSite apropriados.
4. Implemente Tempos de Expiração Curtos
Os JWTs são projetados para serem sem estado, o que significa que são válidos até que expirem. No entanto, quanto mais tempo um token é válido, maior o risco se for interceptado. A AWS recomenda usar tempos de expiração curtos para tokens de acesso. Ao manter o TTL (Time To Live) curto, você limita o dano que um atacante pode causar se conseguir roubar o token.
O Padrão de Token de Atualização
Para manter uma experiência de usuário fluida sem aumentar os riscos de segurança, os desenvolvedores frequentemente usam uma combinação de tokens de acesso de curta duração e tokens de atualização de duração mais longa. O token de acesso concede acesso imediato à API, enquanto o token de atualização é usado para obter um novo token de acesso. Os tokens de atualização devem ser armazenados com segurança, frequentemente em cookies HttpOnly, e ter um tempo de expiração mais longo.
5. Lidando com a Revogação de Tokens
Um dos desafios intrínsecos dos JWTs é que eles são sem estado. Uma vez emitido, um token válido permanece válido até que expire, mesmo que o usuário faça logout ou altere sua senha. Isso torna a revogação difícil.
Tempos TTL Curtos como Estratégia de Revogação
Como mencionado, a maneira mais eficaz de lidar com a revogação é manter o tempo de expiração muito curto. Se um token for comprometido, o atacante só terá um tempo limitado para usá-lo.
Listas Negras
Para aplicativos que exigem revogação imediata, você pode implementar uma lista negra com estado. Quando um usuário faz logout ou sua sessão é invalidada, você adiciona a ID do token (JTI) a um banco de dados ou cache. Antes de validar um token, o servidor verifica se o JTI está na lista negra. No entanto, essa abordagem exige manter estado, o que contradiz a natureza sem estado dos JWTs.
6. Valide as Declarações do Token
Ao receber um JWT, seu servidor deve realizar uma validação rigorosa. A AWS detalha a importância de validar as declarações Emitente (iss), Público-alvo (aud) e Expiração (exp).
- Emitente: Certifique-se de que o token foi emitido pelo seu aplicativo.
- Público-alvo: Certifique-se de que o token é destinado à sua API.
- Expiração: Sempre verifique a declaração
exppara garantir que o token não tenha expirado.
Falhar ao validar essas declarações pode levar a bypasses de autorização, onde um usuário ganha acesso a recursos aos quais não deveria ter acesso.
7. Considere Alternativas como PASETO
Embora os JWTs sejam amplamente usados, eles têm uma história de falhas de segurança. Por exemplo, a vulnerabilidade do algoritmo "none" permitia que atacantes forjassem tokens. HackerNoon discute o surgimento do PASETO (Plataforma para Autenticação, Segurança e Criptografia de Tokens), um novo padrão de token projetado para abordar as vulnerabilidades do JWT. O PASETO suporta chaves simétricas e assimétricas e é projetado para ser mais seguro por padrão. Embora os JWTs ainda sejam o padrão, entender alternativas como o PASETO é crucial para arquitetos que tomam decisões de longo prazo.
Perguntas Frequentes
Qual é a diferença entre HS256 e RS256?
HS256 (HMAC com SHA-256) usa uma chave secreta compartilhada entre o cliente e o servidor. RS256 (RSA com SHA-256) usa uma chave privada para assinar o token e uma chave pública para verificá-lo. RS256 é geralmente considerado mais seguro para sistemas distribuídos porque a chave privada nunca sai do servidor.
Posso revogar um JWT imediatamente?
Como os JWTs são sem estado, você não pode tecnicamente revogar um JWT imediatamente sem manter uma lista negra ou usar tempos de expiração curtos. A solução mais prática é usar tokens de acesso de curta duração.
O LocalStorage é seguro para JWTs?
Não, o LocalStorage é vulnerável a ataques XSS. Se o seu aplicativo for comprometido, um atacante pode ler o LocalStorage e roubar o JWT. Cookies HttpOnly são o mecanismo de armazenamento recomendado para segurança.
Conclusão
Segurar JWTs requer uma abordagem em camadas. Ao usar HTTPS, gerenciar segredos com segurança, armazenar tokens em cookies HttpOnly, implementar tempos de expiração curtos e validar declarações rigorosamente, você pode reduzir significativamente o risco de roubo e uso indevido de tokens. Conforme o cenário de segurança da web evolui, ficar informado sobre as melhores práticas e alternativas como o PASETO é essencial para manter uma postura de segurança robusta.
Referências
- JWT vs PASETO: What's the Best Tool for Generating Secure Tokens?
- How to Build a Secure Nest.js REST API Using JWT and MongoDB
- How to secure API Gateway HTTP endpoints with JWT authorizer
- Best of 2021 – How to Revoke JSON Web Tokens (JWTs)
- JSON Web tokens (JWT): how to use them safely
- How to Create a JWT Secret in Node.js (Best Practices + Examples)
- How to monitor, optimize, and secure Amazon Cognito machine-to-machine authorization