1
$\begingroup$

I'm currently implementing token-based auth with refresh tokens in my .NET app. Right now I have a custom RefreshTokens collection in my ApplicationUser:

public class ApplicationUser : IdentityUser
{
    public virtual ICollection<RefreshToken> RefreshTokens { get; set; } = new List<RefreshToken>();
}

I noticed that ASP.NET Identity generates an AspNetUserTokens table by default. Am I reinventing the wheel here? Could I just use UserManager's token methods (SetAuthenticationTokenAsync/GetAuthenticationTokenAsync) instead of managing my own token service? Do I need to implement my own TokenProvider?

 public async Task<LoginResponse> LoginAsync(LoginPayload request)
 {
     var user = await userManager.FindByEmailAsync(request.Username);
     if (user == null || !await userManager.CheckPasswordAsync(user, request.Password))
         throw new Exception("Invalid email or password");

     if(!user.EmailConfirmed)
         throw new Exception("Email not confirmed");

     var accessToken = tokenService.GenerateAccessToken(user);
     var refreshToken = tokenService.GenerateRefreshToken();

     user.RefreshTokens.Add(refreshToken);
     await context.SaveChangesAsync();

     return new LoginResponse(
         accessToken,
         refreshToken.Token,
         (int)(refreshToken.ExpiresAt - DateTimeOffset.UtcNow).TotalMilliseconds,
         user.UserName!
     );
 }

 public async Task<LoginResponse> RefreshTokenAsync(string accessToken, string refreshToken)
 {
     var principal = tokenService.GetPrincipalFromExpiredToken(accessToken);
     if (principal == null)
         throw new Exception("Invalid access token");

     var user = await userManager.FindByNameAsync(principal.Identity!.Name!);
     if (user == null)
         throw new Exception("User not found");

     var existingToken = await context.RefreshToken
         .FirstOrDefaultAsync(rt => rt.Token == refreshToken);
     if (existingToken == null || existingToken.ExpiresAt < DateTime.UtcNow)
         throw new Exception("Invalid or expired refresh token");

     var newAccessToken = tokenService.GenerateAccessToken(user);
     var newRefreshToken = tokenService.GenerateRefreshToken();

     context.RefreshToken.Remove(existingToken);
     user.RefreshTokens.Add(newRefreshToken);
     await context.SaveChangesAsync();

     return new LoginResponse(
         newAccessToken,
         newRefreshToken.Token,
         (int)(newRefreshToken.ExpiresAt - DateTimeOffset.UtcNow).TotalMilliseconds,
         user.UserName!
     );
 }
$\endgroup$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.