Pular para o conteúdo
.NETPor que e como implementar refresh token
Módulo 06APIs em Produção

Por que e como implementar refresh token

avancado 50 min de leitura·Atualizado · .NET 9
Resumo

Tokens de acesso (JWT) devem ter vida curta por segurança, mas pedir login a cada 15 minutos é ruim. O refresh token renova o acesso sem novas credenciais, com armazenamento e rotação seguros.

1. Objetivos de Aprendizagem#

  • Explicar por que separar access token e refresh token.
  • Emitir e persistir o refresh token no usuário.
  • Implementar o endpoint de renovação com rotação.

2. Pré-requisitos#

  • JWT e autenticação (Módulo 40).

3. Conceito#

  • Access token (JWT): curto (ex.: 15 min), stateless, enviado em toda requisição.
  • Refresh token: longo (ex.: 7 dias), opaco, guardado no servidor, usado só para obter um novo access token.

O porquê: se o access token vazar, expira rápido; o refresh token, guardado e revogável, permite invalidar sessões. A rotação (emitir um novo refresh a cada uso e invalidar o anterior) detecta reuso indevido.

Fluxo de renovação com rotação:

Carregando diagrama…

4. Mão na Massa#

4.1. Setup#

Adicione campos ao ApplicationUser:

C#
public class ApplicationUser : IdentityUser
{
    public string? RefreshToken { get; set; }
    public DateTime RefreshTokenExpiryTime { get; set; }
}

Gere a migration correspondente.

4.2. Implementação Passo a Passo#

  1. Gerar refresh token aleatório e seguro:
C#
private static string GenerateRefreshToken()
{
    var bytes = new byte[64];
    using var rng = System.Security.Cryptography.RandomNumberGenerator.Create();
    rng.GetBytes(bytes);
    return Convert.ToBase64String(bytes);
}
  1. No login, emitir os dois e persistir o refresh:
C#
var accessToken = CreateToken(user, roles);
var refreshToken = GenerateRefreshToken();
user.RefreshToken = refreshToken;
user.RefreshTokenExpiryTime = DateTime.UtcNow.AddDays(7);
await _userManager.UpdateAsync(user);
return new TokenDto(accessToken, refreshToken);
  1. Endpoint de renovação com validação e rotação:
C#
public async Task<TokenDto> RefreshAsync(TokenDto tokenDto)
{
    var principal = GetPrincipalFromExpiredToken(tokenDto.AccessToken);
    var user = await _userManager.FindByNameAsync(principal.Identity!.Name!);

    if (user is null ||
        user.RefreshToken != tokenDto.RefreshToken ||
        user.RefreshTokenExpiryTime <= DateTime.UtcNow)
        throw new RefreshTokenBadRequestException();

    var roles = await _userManager.GetRolesAsync(user);
    var newAccess = CreateToken(user, roles);
    var newRefresh = GenerateRefreshToken();   // rotação
    user.RefreshToken = newRefresh;
    await _userManager.UpdateAsync(user);

    return new TokenDto(newAccess, newRefresh);
}

GetPrincipalFromExpiredToken valida a assinatura com ValidateLifetime = false.

4.3. Executando#

Shell
curl -X POST http://localhost:5000/api/token/refresh \
  -H "Content-Type: application/json" \
  -d '{"accessToken":"<expirado>","refreshToken":"<refresh>"}'

5. Exemplo Completo#

Fluxo: login → (access + refresh). Access expira → cliente chama /token/refresh → recebe novos tokens (refresh rotacionado). Logout → limpar RefreshToken do usuário.

6. Boas Práticas e Armadilhas#

FaçaEvite
Gerar refresh com RNG criptográficoGuid/Random como refresh token
Rotacionar o refresh a cada usoReutilizar o mesmo refresh indefinidamente
Validar assinatura mesmo no token expiradoDesligar toda validação para "ler" o token
Atenção

ao renovar, valide a assinatura do access token expirado (só ValidateLifetime = false). Nunca aceite qualquer token sem verificar a assinatura.

7. Segurança e Produção#

  • Refresh tokens são credenciais de longa duração: armazene com cuidado e permita revogação (logout, troca de senha).
  • Detecte reuso de refresh já rotacionado como possível roubo e invalide toda a cadeia.
  • Sempre HTTPS.

8. Exercícios#

  • Fácil: implemente logout limpando o RefreshToken.
  • Médio: invalide todos os refresh tokens ao trocar a senha.
  • Desafio: implemente detecção de reuso (refresh já usado → revoga a sessão).

9. Resumo#

Access tokens curtos + refresh tokens longos e rotacionados equilibram segurança e experiência. Refresh é gerado com RNG seguro, persistido, revogável e sempre trafega sob HTTPS.

10. Próximos Passos#

Módulo 13: binding de configuração e Options Pattern.

11. Referências#

41-01 — Por que e como implementar refresh token | Curso ASP.NET Core