35 lines
1.3 KiB
C#
35 lines
1.3 KiB
C#
using FluentAssertions;
|
|
|
|
namespace StellaOps.Audit.ReplayToken.Tests;
|
|
|
|
public sealed partial class ReplayTokenSecurityTests
|
|
{
|
|
[Fact]
|
|
public void TokenWithExpiration_CanonicalFormat_IncludesExpiryTimestamp()
|
|
{
|
|
var fixedTime = new DateTimeOffset(2025, 6, 15, 12, 0, 0, TimeSpan.Zero);
|
|
var expiresAt = fixedTime.AddHours(1);
|
|
var token = new ReplayToken("abc123", fixedTime, expiresAt, ReplayToken.DefaultAlgorithm, ReplayToken.VersionWithExpiration);
|
|
|
|
var canonical = token.Canonical;
|
|
|
|
canonical.Should().Contain(expiresAt.ToUnixTimeSeconds().ToString());
|
|
canonical.Split(':').Should().HaveCount(5, "v2.0 format should have 5 parts including expiry");
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseToken_WithExpiration_RoundTrip_PreservesExpiration()
|
|
{
|
|
var fixedTime = new DateTimeOffset(2025, 6, 15, 12, 0, 0, TimeSpan.Zero);
|
|
var generator = CreateGenerator(fixedTime);
|
|
var request = CreateRequest();
|
|
var originalToken = generator.GenerateWithExpiration(request, TimeSpan.FromHours(2));
|
|
|
|
var parsed = ReplayToken.Parse(originalToken.Canonical);
|
|
|
|
parsed.Value.Should().Be(originalToken.Value);
|
|
parsed.Version.Should().Be(ReplayToken.VersionWithExpiration);
|
|
parsed.ExpiresAt.Should().Be(originalToken.ExpiresAt);
|
|
}
|
|
}
|