ASP.NET-Identität: Benutzerdefinierte RefreshTokens vs. integriertes AspNetUserToken
Posted: 03 Jan 2025, 13:09
Ich implementieren derzeit eine tokenbasierte Authentifizierung mit Aktualisierungstokens in meiner .NET-App. Im Moment habe ich eine benutzerdefinierte RefreshTokens-Sammlung in meinem ApplicationUser:
Mir ist aufgefallen, dass ASP.NET Identity standardmäßig eine AspNetUserTokens-Tabelle generiert. Erfinde ich hier das Rad neu? Könnte ich einfach die Token-Methoden von UserManager (SetAuthenticationTokenAsync/GetAuthenticationTokenAsync) verwenden, anstatt meinen eigenen Token-Dienst zu verwalten? Muss ich meinen eigenen TokenProvider implementieren?
Code: Select all
public class ApplicationUser : IdentityUser
{
public virtual ICollection RefreshTokens { get; set; } = new List();
}
Code: Select all
public async Task 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 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!
);
}