diff --git a/web/backend/Features/Features.Auth.Tests/Commands/RegisterUserHandlerTests.cs b/web/backend/Features/Features.Auth.Tests/Commands/RegisterUserHandlerTests.cs index d9bde15c..abd331be 100644 --- a/web/backend/Features/Features.Auth.Tests/Commands/RegisterUserHandlerTests.cs +++ b/web/backend/Features/Features.Auth.Tests/Commands/RegisterUserHandlerTests.cs @@ -92,13 +92,13 @@ public class RegisterUserHandlerTests ); _tokenServiceMock - .Setup(x => x.GenerateAccessToken(It.IsAny())) + .Setup(x => x.GenerateAccessToken(It.IsAny(), It.IsAny())) .Returns("access-token"); _tokenServiceMock - .Setup(x => x.GenerateRefreshToken(It.IsAny())) + .Setup(x => x.GenerateRefreshToken(It.IsAny(), It.IsAny())) .Returns("refresh-token"); _tokenServiceMock - .Setup(x => x.GenerateConfirmationToken(It.IsAny())) + .Setup(x => x.GenerateConfirmationToken(It.IsAny(), It.IsAny())) .Returns("confirmation-token"); RegistrationPayload result = await _handler.Handle(command, CancellationToken.None); @@ -192,10 +192,10 @@ public class RegisterUserHandlerTests .ReturnsAsync(new UserAccount { UserAccountId = Guid.NewGuid() }); _tokenServiceMock - .Setup(x => x.GenerateAccessToken(It.IsAny())) + .Setup(x => x.GenerateAccessToken(It.IsAny(), It.IsAny())) .Returns("access-token"); _tokenServiceMock - .Setup(x => x.GenerateRefreshToken(It.IsAny())) + .Setup(x => x.GenerateRefreshToken(It.IsAny(), It.IsAny())) .Returns("refresh-token"); await _handler.Handle(command, CancellationToken.None); @@ -241,10 +241,10 @@ public class RegisterUserHandlerTests ); _tokenServiceMock - .Setup(x => x.GenerateAccessToken(It.IsAny())) + .Setup(x => x.GenerateAccessToken(It.IsAny(), It.IsAny())) .Returns("access-token"); _tokenServiceMock - .Setup(x => x.GenerateRefreshToken(It.IsAny())) + .Setup(x => x.GenerateRefreshToken(It.IsAny(), It.IsAny())) .Returns("refresh-token"); _mediatorMock .Setup(x => diff --git a/web/backend/Features/Features.Auth.Tests/Commands/ResendConfirmationEmailHandlerTests.cs b/web/backend/Features/Features.Auth.Tests/Commands/ResendConfirmationEmailHandlerTests.cs index 56147230..5905cafc 100644 --- a/web/backend/Features/Features.Auth.Tests/Commands/ResendConfirmationEmailHandlerTests.cs +++ b/web/backend/Features/Features.Auth.Tests/Commands/ResendConfirmationEmailHandlerTests.cs @@ -37,7 +37,7 @@ public class ResendConfirmationEmailHandlerTests _authRepositoryMock.Setup(x => x.GetUserByIdAsync(userId)).ReturnsAsync(user); _authRepositoryMock.Setup(x => x.IsUserVerifiedAsync(userId)).ReturnsAsync(false); - _tokenServiceMock.Setup(x => x.GenerateConfirmationToken(user)).Returns("fresh-token"); + _tokenServiceMock.Setup(x => x.GenerateConfirmationToken(user.UserAccountId, user.Username)).Returns("fresh-token"); await _handler.Handle(new ResendConfirmationEmailCommand(userId), CancellationToken.None); diff --git a/web/backend/Features/Features.Auth.Tests/Queries/LoginHandlerTests.cs b/web/backend/Features/Features.Auth.Tests/Queries/LoginHandlerTests.cs index 9121cdcf..86104a7b 100644 --- a/web/backend/Features/Features.Auth.Tests/Queries/LoginHandlerTests.cs +++ b/web/backend/Features/Features.Auth.Tests/Queries/LoginHandlerTests.cs @@ -61,10 +61,10 @@ public class LoginHandlerTests .Setup(x => x.Verify(It.IsAny(), It.IsAny())) .Returns(true); _tokenServiceMock - .Setup(x => x.GenerateAccessToken(It.IsAny())) + .Setup(x => x.GenerateAccessToken(It.IsAny(), It.IsAny())) .Returns("access-token"); _tokenServiceMock - .Setup(x => x.GenerateRefreshToken(It.IsAny())) + .Setup(x => x.GenerateRefreshToken(It.IsAny(), It.IsAny())) .Returns("refresh-token"); LoginPayload result = await _handler.Handle( diff --git a/web/backend/Features/Features.Auth/Commands/Login/LoginHandler.cs b/web/backend/Features/Features.Auth/Commands/Login/LoginHandler.cs index 9921610a..32db7718 100644 --- a/web/backend/Features/Features.Auth/Commands/Login/LoginHandler.cs +++ b/web/backend/Features/Features.Auth/Commands/Login/LoginHandler.cs @@ -35,8 +35,8 @@ public class LoginHandler( if (!passwordInfrastructure.Verify(request.Password, activeCred.Hash)) throw new UnauthorizedException("Invalid username or password."); - string accessToken = tokenService.GenerateAccessToken(user); - string refreshToken = tokenService.GenerateRefreshToken(user); + string accessToken = tokenService.GenerateAccessToken(user.UserAccountId, user.Username); + string refreshToken = tokenService.GenerateRefreshToken(user.UserAccountId, user.Username); return new LoginPayload(user.UserAccountId, user.Username, refreshToken, accessToken); } diff --git a/web/backend/Features/Features.Auth/Commands/RegisterUser/RegisterUserHandler.cs b/web/backend/Features/Features.Auth/Commands/RegisterUser/RegisterUserHandler.cs index 90c03a73..f6202652 100644 --- a/web/backend/Features/Features.Auth/Commands/RegisterUser/RegisterUserHandler.cs +++ b/web/backend/Features/Features.Auth/Commands/RegisterUser/RegisterUserHandler.cs @@ -48,9 +48,18 @@ public class RegisterUserHandler( } ); - string accessToken = tokenService.GenerateAccessToken(createdUser); - string refreshToken = tokenService.GenerateRefreshToken(createdUser); - string confirmationToken = tokenService.GenerateConfirmationToken(createdUser); + string accessToken = tokenService.GenerateAccessToken( + createdUser.UserAccountId, + createdUser.Username + ); + string refreshToken = tokenService.GenerateRefreshToken( + createdUser.UserAccountId, + createdUser.Username + ); + string confirmationToken = tokenService.GenerateConfirmationToken( + createdUser.UserAccountId, + createdUser.Username + ); if (string.IsNullOrEmpty(accessToken) || string.IsNullOrEmpty(refreshToken)) return new RegistrationPayload( diff --git a/web/backend/Features/Features.Auth/Commands/ResendConfirmationEmail/ResendConfirmationEmailHandler.cs b/web/backend/Features/Features.Auth/Commands/ResendConfirmationEmail/ResendConfirmationEmailHandler.cs index 0fa817b1..f8227d65 100644 --- a/web/backend/Features/Features.Auth/Commands/ResendConfirmationEmail/ResendConfirmationEmailHandler.cs +++ b/web/backend/Features/Features.Auth/Commands/ResendConfirmationEmail/ResendConfirmationEmailHandler.cs @@ -32,7 +32,10 @@ public class ResendConfirmationEmailHandler( if (await authRepository.IsUserVerifiedAsync(request.UserId)) return; // Already confirmed, no-op - string confirmationToken = tokenService.GenerateConfirmationToken(user); + string confirmationToken = tokenService.GenerateConfirmationToken( + user.UserAccountId, + user.Username + ); await mediator.Send( new SendResendConfirmationEmailCommand(user.FirstName, user.Email, confirmationToken), cancellationToken diff --git a/web/backend/Features/Features.Auth/Services/ITokenService.cs b/web/backend/Features/Features.Auth/Services/ITokenService.cs index c3bc2c89..b9fdb2c1 100644 --- a/web/backend/Features/Features.Auth/Services/ITokenService.cs +++ b/web/backend/Features/Features.Auth/Services/ITokenService.cs @@ -48,19 +48,19 @@ public interface ITokenService /// Generates a signed access token for the given user, expiring after /// hours. /// - string GenerateAccessToken(UserAccount user); + string GenerateAccessToken(Guid userId, string username); /// /// Generates a signed refresh token for the given user, expiring after /// hours. /// - string GenerateRefreshToken(UserAccount user); + string GenerateRefreshToken(Guid userId, string username); /// /// Generates a signed confirmation token for the given user, expiring after /// hours. /// - string GenerateConfirmationToken(UserAccount user); + string GenerateConfirmationToken(Guid userId, string username); /// Validates an access token's signature and expiration and extracts the caller's identity. diff --git a/web/backend/Features/Features.Auth/Services/TokenService.cs b/web/backend/Features/Features.Auth/Services/TokenService.cs index 5dc8dfa4..6f6729c4 100644 --- a/web/backend/Features/Features.Auth/Services/TokenService.cs +++ b/web/backend/Features/Features.Auth/Services/TokenService.cs @@ -49,40 +49,30 @@ public class TokenService : ITokenService } /// - public string GenerateAccessToken(UserAccount user) + public string GenerateAccessToken(Guid userId, string username) { DateTime expiresAt = DateTime.UtcNow.AddHours(TokenServiceExpirationHours.AccessTokenHours); - return _tokenInfrastructure.GenerateJwt( - user.UserAccountId, - user.Username, - expiresAt, - _accessTokenSecret - ); + return _tokenInfrastructure.GenerateJwt(userId, username, expiresAt, _accessTokenSecret); } /// - public string GenerateRefreshToken(UserAccount user) + public string GenerateRefreshToken(Guid userId, string username) { DateTime expiresAt = DateTime.UtcNow.AddHours( TokenServiceExpirationHours.RefreshTokenHours ); - return _tokenInfrastructure.GenerateJwt( - user.UserAccountId, - user.Username, - expiresAt, - _refreshTokenSecret - ); + return _tokenInfrastructure.GenerateJwt(userId, username, expiresAt, _refreshTokenSecret); } /// - public string GenerateConfirmationToken(UserAccount user) + public string GenerateConfirmationToken(Guid userId, string username) { DateTime expiresAt = DateTime.UtcNow.AddHours( TokenServiceExpirationHours.ConfirmationTokenHours ); return _tokenInfrastructure.GenerateJwt( - user.UserAccountId, - user.Username, + userId, + username, expiresAt, _confirmationTokenSecret ); @@ -114,8 +104,8 @@ public class TokenService : ITokenService if (user == null) throw new UnauthorizedException("User account not found"); - string newAccess = GenerateAccessToken(user); - string newRefresh = GenerateRefreshToken(user); + string newAccess = GenerateAccessToken(user.UserAccountId, user.Username); + string newRefresh = GenerateRefreshToken(user.UserAccountId, user.Username); return new RefreshTokenResult(user, newRefresh, newAccess); }