using BuildingBlock.Identity.Contracts.Conventions; using BuildingBlock.Identity.Contracts.Requests; using BuildingBlock.Identity.Contracts.Responses; using Thalos.Service.Application.Sessions; using Thalos.Service.Application.UseCases; using Thalos.Service.Identity.Abstractions.Contracts; using IdentityIssueRequest = BuildingBlock.Identity.Contracts.Requests.IssueIdentityTokenRequest; using IdentityIssueResponse = BuildingBlock.Identity.Contracts.Responses.IssueIdentityTokenResponse; using SessionRefreshRequest = Thalos.Service.Identity.Abstractions.Contracts.RefreshIdentitySessionRequest; namespace Thalos.Service.Application.UnitTests; public class RefreshIdentitySessionUseCaseTests { [Fact] public async Task HandleAsync_WhenRefreshTokenValid_ReissuesSessionTokens() { var useCase = new RefreshIdentitySessionUseCase(new FakeIssueUseCase(), new FakeSessionTokenCodec()); var response = await useCase.HandleAsync(new SessionRefreshRequest("refresh-token", "corr-1", IdentityAuthProvider.Google)); Assert.Equal("token-new", response.AccessToken); Assert.Equal(3000, response.ExpiresInSeconds); Assert.Equal("google-sub-1", response.SubjectId); Assert.Equal("tenant-2", response.TenantId); Assert.Equal("refresh-google-sub-1-tenant-2", response.RefreshToken); } [Fact] public async Task HandleAsync_WhenRefreshTokenInvalid_ReturnsEmptyPayload() { var useCase = new RefreshIdentitySessionUseCase(new FakeIssueUseCase(), new InvalidSessionTokenCodec()); var response = await useCase.HandleAsync(new SessionRefreshRequest("bad-token", "corr-2")); Assert.Equal(string.Empty, response.AccessToken); Assert.Equal(0, response.ExpiresInSeconds); Assert.Equal(string.Empty, response.RefreshToken); } private sealed class FakeIssueUseCase : IIssueIdentityTokenUseCase { public Task HandleAsync(IdentityIssueRequest request) { return Task.FromResult(new IdentityIssueResponse("token-new", 3000)); } } private sealed class FakeSessionTokenCodec : IIdentitySessionTokenCodec { public string Encode(IdentitySessionDescriptor descriptor) { return $"refresh-{descriptor.SubjectId}-{descriptor.TenantId}"; } public bool TryDecode(string token, out IdentitySessionDescriptor descriptor) { descriptor = new IdentitySessionDescriptor( "google-sub-1", "tenant-2", IdentityAuthProvider.Google, DateTimeOffset.UtcNow.AddHours(1)); return true; } } private sealed class InvalidSessionTokenCodec : IIdentitySessionTokenCodec { public string Encode(IdentitySessionDescriptor descriptor) => string.Empty; public bool TryDecode(string token, out IdentitySessionDescriptor descriptor) { descriptor = new IdentitySessionDescriptor(string.Empty, string.Empty, IdentityAuthProvider.InternalJwt, DateTimeOffset.MinValue); return false; } } }