86 lines
2.8 KiB
C#
86 lines
2.8 KiB
C#
using BuildingBlock.Identity.Contracts.Conventions;
|
|
using Thalos.Service.Application.Secrets;
|
|
using Thalos.Service.Application.Sessions;
|
|
|
|
namespace Thalos.Service.Application.UnitTests;
|
|
|
|
public class HmacIdentitySessionTokenCodecTests
|
|
{
|
|
[Fact]
|
|
public void EncodeAndTryDecode_WhenTokenValid_RoundTripsDescriptor()
|
|
{
|
|
var codec = new HmacIdentitySessionTokenCodec(new FakeSecretMaterialProvider());
|
|
var descriptor = new IdentitySessionDescriptor(
|
|
"user-9",
|
|
"tenant-9",
|
|
IdentityAuthProvider.AzureAd,
|
|
DateTimeOffset.UtcNow.AddMinutes(5));
|
|
|
|
var token = codec.Encode(descriptor);
|
|
var ok = codec.TryDecode(token, out var decoded);
|
|
|
|
Assert.True(ok);
|
|
Assert.Equal("user-9", decoded.SubjectId);
|
|
Assert.Equal("tenant-9", decoded.TenantId);
|
|
Assert.Equal(IdentityAuthProvider.AzureAd, decoded.Provider);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryDecode_WhenTokenTampered_ReturnsFalse()
|
|
{
|
|
var codec = new HmacIdentitySessionTokenCodec(new FakeSecretMaterialProvider());
|
|
var descriptor = new IdentitySessionDescriptor(
|
|
"user-9",
|
|
"tenant-9",
|
|
IdentityAuthProvider.InternalJwt,
|
|
DateTimeOffset.UtcNow.AddMinutes(5));
|
|
|
|
var token = codec.Encode(descriptor) + "tamper";
|
|
|
|
var ok = codec.TryDecode(token, out _);
|
|
|
|
Assert.False(ok);
|
|
}
|
|
|
|
[Fact]
|
|
public void Encode_WhenSigningSecretUnavailable_ThrowsExplicitRuntimeError()
|
|
{
|
|
var codec = new HmacIdentitySessionTokenCodec(new MissingSecretMaterialProvider());
|
|
var descriptor = new IdentitySessionDescriptor(
|
|
"user-9",
|
|
"tenant-9",
|
|
IdentityAuthProvider.InternalJwt,
|
|
DateTimeOffset.UtcNow.AddMinutes(5));
|
|
|
|
var error = Assert.Throws<InvalidOperationException>(() => codec.Encode(descriptor));
|
|
|
|
Assert.Contains("SessionSigning", error.Message, StringComparison.Ordinal);
|
|
}
|
|
|
|
private sealed class FakeSecretMaterialProvider : IIdentitySecretMaterialProvider
|
|
{
|
|
public bool TryGetSecret(string secretKey, out string secretValue)
|
|
{
|
|
secretValue = "unit-test-secret";
|
|
return true;
|
|
}
|
|
|
|
public string GetSecret(string secretKey) => "unit-test-secret";
|
|
}
|
|
|
|
private sealed class MissingSecretMaterialProvider : IIdentitySecretMaterialProvider
|
|
{
|
|
public bool TryGetSecret(string secretKey, out string secretValue)
|
|
{
|
|
secretValue = string.Empty;
|
|
return false;
|
|
}
|
|
|
|
public string GetSecret(string secretKey)
|
|
{
|
|
throw new InvalidOperationException(
|
|
$"Identity secret '{secretKey}' is not configured for the current runtime.");
|
|
}
|
|
}
|
|
}
|