Se você trabalha com autenticação em Single Page Applications (SPAs) ou aplicativos mobile, provavelmente usa JWT (JSON Web Tokens). O problema é que a maioria dos tutoriais por aí ensina o “caminho feliz”: o usuário loga, recebe um token com validade de 30 dias, guarda no localStorage e vida que segue.
No mundo real, isso é um prato cheio para ataques de XSS (Cross-Site Scripting) ou exfiltração de dados. Se um atacante roubar esse token, ele tem acesso livre à conta do seu usuário até o token expirar. É aqui que entra a Defesa de Sessão Profissional.
Neste artigo, vou te mostrar como implementamos a Rotação de Refresh Tokens com Detecção de Reuso na prática, usando NestJS e Drizzle ORM.
O Calcanhar de Aquiles do JWT Tradicional
O JWT é stateless (sem estado). Isso é ótimo para escalabilidade, mas péssimo para revogação. Uma vez emitido, um Access Token não pode ser cancelado facilmente sem criar uma “blacklist” no banco de dados, o que mata a vantagem de ser stateless.
A arquitetura segura padrão do mercado dita o seguinte:
- Access Token: Tempo de vida curtíssimo (ex: 15 minutos).
- Refresh Token: Tempo de vida maior (ex: 7 dias), usado apenas para pegar um novo Access Token.
Mas e se o atacante roubar o Refresh Token? Ele pode ficar renovando o acesso para sempre. É aí que a brincadeira fica séria.
A Solução: Rotação de JWT + Detecção de Reuso
Para ambientes críticos (fintechs, healthtechs), não basta ter um Refresh Token. Você precisa rotacioná-lo. E mais importante: você precisa saber se ele vazou.
1. Rotação do Refresh Token (Refresh Token Rotation)
A cada vez que o front-end envia um Refresh Token válido para a sua API NestJS pedindo um novo Access Token, o servidor invalida o Refresh Token antigo e devolve um par novinho (Novo Access Token + Novo Refresh Token). O token antigo entra para o histórico.
2. A Mágica da Detecção de Reuso (Reuse Detection)
E se o token antigo tentar ser usado de novo? Se o seu sistema recebe um Refresh Token que já foi rotacionado (já utilizado), isso significa uma coisa: a sessão foi comprometida. O usuário legítimo e o atacante estão brigando pelo acesso, ou a rede foi clonada.
Neste momento, a API não apenas nega o acesso. Ela detona a sessão inteira. Toda a família de tokens gerada a partir daquele login inicial é revogada imediatamente. O atacante é expulso, e o usuário legítimo será forçado a fazer login novamente (o que é o cenário mais seguro).
Como isso funciona no Código (NestJS + Drizzle)
No Secure NestJS Drizzle Template, essa arquitetura já vem pronta. Nós modelamos o banco de dados para rastrear a “família” (Session ID) de cada token.
Quando a rota /auth/refresh é chamada:
- O Guard do NestJS valida a assinatura do token (usando chave pública RS256).
- O serviço de Auth verifica no banco (via Drizzle ORM) se a jti (JWT ID) daquele token consta como já utilizada.
- Se constar: Dispara um alerta de segurança (
Audit Log), bloqueia a família de sessão e retorna401 Unauthorized. - Se for inédito: Emite novos tokens e marca o atual como “utilizado”.
Conclusão: Pare de confiar cegamente nos seus tokens
Segurança em APIs não é sobre impedir todos os ataques, mas sim sobre reduzir a janela de oportunidade e conter os danos quando um vazamento acontece. Com a Rotação de JWT e a Detecção de Reuso, um token roubado tem um valor quase nulo para o atacante, pois a primeira tentativa de usá-lo vai implodir o próprio acesso dele.
Quer economizar dezenas de horas implementando e testando essa lógica do zero?
🔗 Faça um fork do Secure NestJS Drizzle Template no GitHub e veja o código em produção.
E se a sua empresa precisa de ajuda para estruturar uma arquitetura backend resiliente e passar por auditorias de segurança com tranquilidade, dá uma passada lá no Ramos da Informática e vamos bater um papo.
