Autenticação Invisível: A Arquitetura de Refresh Tokens
Evite que seu usuário seja deslogado a cada 15 minutos sem comprometer a segurança da aplicação. Aprenda a implementar o fluxo de Refresh Tokens e JWTs de curta duração.
O JSON Web Token (JWT) tem um problema inerente de arquitetura (chamado Stateless): depois que você emite um JWT dizendo 'Esse é o Joãozinho', você não pode cancelar ou anular esse token até que ele expire por conta própria. Se um hacker roubar o JWT do Joãozinho que tem validade de 1 ano, ele terá acesso total à conta por 365 dias.
O Trade-off de Segurança
Para resolver o problema do roubo, a regra de ouro em segurança é gerar JWTs que expiram extremamente rápido (ex: 15 minutos). Mas, se fizermos isso, o usuário será deslogado da nossa plataforma de 15 em 15 minutos, o que destruiria a experiência (UX).
A Solução: Refresh Tokens
A arquitetura de Refresh Token separa o papel de Autenticação em duas chaves distintas:
- O Token Principal (Access Token): É um JWT comum. Dura apenas 15 minutos. Usado em todas as chamadas de API (no header
Authorization: Bearer). - O Refresh Token: É um código opaco (geralmente um UUID salvo no Banco de Dados). Dura 30 dias. É devolvido na hora do Login junto com o Access Token e, muitas vezes, é guardado de forma segura no Frontend (via HttpOnly Cookie).
O Fluxo Perfeito
O usuário navega normalmente com o seu JWT de 15 minutos. No minuto 16, ele clica no botão 'Meu Perfil'. O seu Backend recusa a requisição e devolve 401 Unauthorized (Token Expired).
O seu Frontend (usando Axios Interceptors) percebe o erro 401. Sem o usuário perceber (invisível na tela), o Frontend chama a rota /refresh-token enviando o código opaco de 30 dias que ele tinha guardado.
export class RefreshTokenService {
public async execute(token: string) {
// 1. Busca no banco de dados se esse Refresh Token existe e não expirou
const userToken = await userTokensRepository.findByToken(token);
if (!userToken) throw new AppError('Refresh Token não encontrado', 401);
// 2. Se o usuário deletou a própria conta ou o Admin baniu o usuário,
// a gente deleta o token do banco e nega a renovação!
// 3. Gera um NOVO JWT com validade de 15 minutos
const newToken = sign({}, process.env.JWT_SECRET, {
subject: userToken.user_id,
expiresIn: '15m'
});
// 4. (Opcional) Rotaciona o Refresh Token antigo apagando-o e gerando outro para mais 30 dias
return { token: newToken };
}
}O Frontend recebe o novo JWT de 15 minutos, repete a chamada que tinha falhado (Meu Perfil) e a tela carrega normalmente. O usuário final não notou absolutamente nada, e a sua segurança arquitetural é de padrão bancário.
A maior vantagem disso: Se o celular do Joãozinho for roubado, o Admin entra no banco de dados e simplesmente APAGA o Refresh Token dele. Nos próximos 15 minutos (quando o JWT atual expirar), o Axios vai tentar renovar o token e o banco vai rejeitar. A sessão no celular roubado é encerrada permanentemente.