139 lines
5.2 KiB
C#
139 lines
5.2 KiB
C#
using BuildingBlock.Identity.Contracts.Conventions;
|
|
using BuildingBlock.Identity.Contracts.Requests;
|
|
using BuildingBlock.Identity.Contracts.Responses;
|
|
using Thalos.Service.Application.Oidc;
|
|
using Thalos.Service.Application.Sessions;
|
|
using Thalos.Service.Application.UseCases;
|
|
using Thalos.Service.Identity.Abstractions.Contracts;
|
|
using ExchangeRequest = BuildingBlock.Identity.Contracts.Requests.ExchangeIdentityProviderTokenRequest;
|
|
using ExchangeResponse = BuildingBlock.Identity.Contracts.Responses.ExchangeIdentityProviderTokenResponse;
|
|
using IdentityIssueRequest = BuildingBlock.Identity.Contracts.Requests.IssueIdentityTokenRequest;
|
|
using IdentityIssueResponse = BuildingBlock.Identity.Contracts.Responses.IssueIdentityTokenResponse;
|
|
|
|
namespace Thalos.Service.Application.UnitTests;
|
|
|
|
public class StartIdentitySessionUseCaseTests
|
|
{
|
|
[Fact]
|
|
public async Task HandleAsync_WhenCalled_IssuesTokenAndRefreshToken()
|
|
{
|
|
var issueUseCase = new FakeIssueUseCase();
|
|
var useCase = new StartIdentitySessionUseCase(
|
|
issueUseCase,
|
|
new FakeExchangeService(),
|
|
new FakeSessionTokenCodec());
|
|
|
|
var response = await useCase.HandleAsync(new StartIdentitySessionRequest("user-1", "tenant-1", IdentityAuthProvider.InternalJwt));
|
|
|
|
Assert.Equal("token-abc", response.AccessToken);
|
|
Assert.Equal(1800, response.ExpiresInSeconds);
|
|
Assert.Equal("user-1", response.SubjectId);
|
|
Assert.Equal("tenant-1", response.TenantId);
|
|
Assert.Equal("refresh-user-1-tenant-1", response.RefreshToken);
|
|
Assert.NotNull(issueUseCase.LastRequest);
|
|
Assert.Equal("user-1", issueUseCase.LastRequest!.SubjectId);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task HandleAsync_WhenGoogleProviderAndExchangeSucceeds_UsesExchangedSubject()
|
|
{
|
|
var issueUseCase = new FakeIssueUseCase();
|
|
var exchangeService = new FakeExchangeService
|
|
{
|
|
NextResponse = new ExchangeResponse(
|
|
"google-sub-123",
|
|
"tenant-1",
|
|
IdentityAuthProvider.Google,
|
|
true)
|
|
};
|
|
|
|
var useCase = new StartIdentitySessionUseCase(
|
|
issueUseCase,
|
|
exchangeService,
|
|
new FakeSessionTokenCodec());
|
|
|
|
var response = await useCase.HandleAsync(new StartIdentitySessionRequest(
|
|
string.Empty,
|
|
"tenant-1",
|
|
IdentityAuthProvider.Google,
|
|
"google-id-token",
|
|
"corr-1"));
|
|
|
|
Assert.Equal("token-abc", response.AccessToken);
|
|
Assert.Equal("google-sub-123", response.SubjectId);
|
|
Assert.Equal(IdentityAuthProvider.Google, response.Provider);
|
|
Assert.NotNull(issueUseCase.LastRequest);
|
|
Assert.Equal("google-sub-123", issueUseCase.LastRequest!.SubjectId);
|
|
Assert.Equal("google-id-token", issueUseCase.LastRequest.ExternalToken);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task HandleAsync_WhenGoogleExchangeFails_ReturnsFailedSession()
|
|
{
|
|
var issueUseCase = new FakeIssueUseCase();
|
|
var exchangeService = new FakeExchangeService
|
|
{
|
|
NextResponse = new ExchangeResponse(
|
|
string.Empty,
|
|
"tenant-1",
|
|
IdentityAuthProvider.Google,
|
|
false)
|
|
};
|
|
var useCase = new StartIdentitySessionUseCase(
|
|
issueUseCase,
|
|
exchangeService,
|
|
new FakeSessionTokenCodec());
|
|
|
|
var response = await useCase.HandleAsync(new StartIdentitySessionRequest(
|
|
string.Empty,
|
|
"tenant-1",
|
|
IdentityAuthProvider.Google,
|
|
"invalid-token",
|
|
"corr-2"));
|
|
|
|
Assert.Equal(string.Empty, response.AccessToken);
|
|
Assert.Equal(string.Empty, response.RefreshToken);
|
|
Assert.Equal(0, response.ExpiresInSeconds);
|
|
Assert.Null(issueUseCase.LastRequest);
|
|
}
|
|
|
|
private sealed class FakeIssueUseCase : IIssueIdentityTokenUseCase
|
|
{
|
|
public IdentityIssueRequest? LastRequest { get; private set; }
|
|
|
|
public Task<IdentityIssueResponse> HandleAsync(IdentityIssueRequest request)
|
|
{
|
|
LastRequest = request;
|
|
return Task.FromResult(new IdentityIssueResponse("token-abc", 1800));
|
|
}
|
|
}
|
|
|
|
private sealed class FakeExchangeService : IIdentityProviderTokenExchangeService
|
|
{
|
|
public ExchangeResponse NextResponse { get; set; } = new(
|
|
string.Empty,
|
|
string.Empty,
|
|
IdentityAuthProvider.Google,
|
|
false);
|
|
|
|
public Task<ExchangeResponse> ExchangeAsync(ExchangeRequest request, CancellationToken cancellationToken = default)
|
|
{
|
|
return Task.FromResult(NextResponse);
|
|
}
|
|
}
|
|
|
|
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(string.Empty, string.Empty, IdentityAuthProvider.InternalJwt, DateTimeOffset.UtcNow);
|
|
return false;
|
|
}
|
|
}
|
|
}
|