66 lines
2.4 KiB
C#
66 lines
2.4 KiB
C#
using Knot.Contracts.Auth.Application.Abstractions;
|
|
using Knot.Contracts.Auth.Application.Auth.DTOs;
|
|
using Knot.Contracts.Auth.Domain;
|
|
using Knot.Shared.Kernel;
|
|
using MediatR;
|
|
|
|
namespace Knot.Modules.Auth.Application.Users.RefreshToken;
|
|
|
|
internal sealed class RefreshTokenCommandHandler : ICommandHandler<RefreshTokenCommand, AuthResponseDto>
|
|
{
|
|
private readonly IUserRepository _userRepository;
|
|
private readonly IJwtTokenProvider _tokenProvider;
|
|
|
|
public RefreshTokenCommandHandler(
|
|
IUserRepository userRepository,
|
|
IJwtTokenProvider tokenProvider)
|
|
{
|
|
_userRepository = userRepository;
|
|
_tokenProvider = tokenProvider;
|
|
}
|
|
|
|
public async Task<Result<AuthResponseDto>> Handle(RefreshTokenCommand request, CancellationToken cancellationToken)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(request.RefreshToken))
|
|
{
|
|
return Result.Failure<AuthResponseDto>(
|
|
new Error("Auth.InvalidRefreshToken", "Refresh token is required"));
|
|
}
|
|
|
|
var user = await _userRepository.GetByRefreshTokenAsync(request.RefreshToken, cancellationToken);
|
|
if (user == null)
|
|
{
|
|
return Result.Failure<AuthResponseDto>(
|
|
new Error("Auth.InvalidRefreshToken", "Invalid or expired refresh token"));
|
|
}
|
|
|
|
// Check if refresh token has expired
|
|
if (user.RefreshTokenExpiry.HasValue && user.RefreshTokenExpiry.Value < DateTime.UtcNow)
|
|
{
|
|
// Clear expired refresh token
|
|
user.SetRefreshToken(null, null);
|
|
await _userRepository.UpdateAsync(user, cancellationToken);
|
|
|
|
return Result.Failure<AuthResponseDto>(
|
|
new Error("Auth.RefreshTokenExpired", "Refresh token has expired. Please login again."));
|
|
}
|
|
|
|
var newAccessToken = _tokenProvider.Generate(user.Id, user.Username, user.DisplayName, user.Avatar);
|
|
|
|
var newRefreshToken = _tokenProvider.GenerateRefreshToken();
|
|
var newRefreshExpiry = _tokenProvider.GetRefreshTokenExpiry();
|
|
user.SetRefreshToken(newRefreshToken, newRefreshExpiry);
|
|
await _userRepository.UpdateAsync(user, cancellationToken);
|
|
|
|
return Result.Success(new AuthResponseDto
|
|
{
|
|
AccessToken = newAccessToken,
|
|
RefreshToken = newRefreshToken,
|
|
UserId = user.Id,
|
|
Username = user.Username,
|
|
DisplayName = user.DisplayName,
|
|
Avatar = user.Avatar
|
|
});
|
|
}
|
|
}
|