// Tests for Account JWT activation claim expiration: RegisterActivation, // CheckActivationExpiry, IsActivationExpired, GetExpiredActivations, // RemoveExpiredActivations, and ActiveActivationCount. // Go reference: server/accounts.go — checkActivation (~line 2943), // activationExpired (~line 2920). using NATS.Server.Auth; namespace NATS.Server.Auth.Tests.Auth; public class ActivationExpirationTests { // Helpers for well-past / well-future dates to avoid timing flakiness. private static DateTime WellFuture => DateTime.UtcNow.AddDays(30); private static DateTime WellPast => DateTime.UtcNow.AddDays(-30); private static ActivationClaim ValidClaim(string subject) => new() { Subject = subject, IssuedAt = DateTime.UtcNow.AddDays(-1), ExpiresAt = WellFuture, Issuer = "AABC123", }; private static ActivationClaim ExpiredClaim(string subject) => new() { Subject = subject, IssuedAt = DateTime.UtcNow.AddDays(-60), ExpiresAt = WellPast, Issuer = "AABC123", }; // --------------------------------------------------------------------------- // RegisterActivation // --------------------------------------------------------------------------- [Fact] public void RegisterActivation_StoresActivation() { // Go ref: accounts.go — checkActivation stores the decoded activation claim. var account = new Account("test"); var claim = ValidClaim("svc.foo"); account.RegisterActivation("svc.foo", claim); var result = account.CheckActivationExpiry("svc.foo"); result.Found.ShouldBeTrue(); } // --------------------------------------------------------------------------- // CheckActivationExpiry // --------------------------------------------------------------------------- [Fact] public void CheckActivationExpiry_Valid_NotExpired() { // Go ref: accounts.go — act.Expires > tn ⇒ checkActivation returns true (not expired). var account = new Account("test"); account.RegisterActivation("svc.valid", ValidClaim("svc.valid")); var result = account.CheckActivationExpiry("svc.valid"); result.Found.ShouldBeTrue(); result.IsExpired.ShouldBeFalse(); result.ExpiresAt.ShouldNotBeNull(); result.TimeToExpiry.ShouldNotBeNull(); result.TimeToExpiry!.Value.ShouldBeGreaterThan(TimeSpan.Zero); } [Fact] public void CheckActivationExpiry_Expired_ReturnsExpired() { // Go ref: accounts.go — act.Expires <= tn ⇒ checkActivation returns false (expired). var account = new Account("test"); account.RegisterActivation("svc.expired", ExpiredClaim("svc.expired")); var result = account.CheckActivationExpiry("svc.expired"); result.Found.ShouldBeTrue(); result.IsExpired.ShouldBeTrue(); result.ExpiresAt.ShouldNotBeNull(); result.TimeToExpiry.ShouldBe(TimeSpan.Zero); } [Fact] public void CheckActivationExpiry_NotFound() { // Go ref: accounts.go — checkActivation returns false when claim is nil/empty token. var account = new Account("test"); var result = account.CheckActivationExpiry("svc.unknown"); result.Found.ShouldBeFalse(); result.IsExpired.ShouldBeFalse(); result.ExpiresAt.ShouldBeNull(); result.TimeToExpiry.ShouldBeNull(); } // --------------------------------------------------------------------------- // IsActivationExpired // --------------------------------------------------------------------------- [Fact] public void IsActivationExpired_Valid_ReturnsFalse() { // Go ref: accounts.go — act.Expires > tn ⇒ not expired. var account = new Account("test"); account.RegisterActivation("svc.ok", ValidClaim("svc.ok")); account.IsActivationExpired("svc.ok").ShouldBeFalse(); } [Fact] public void IsActivationExpired_Expired_ReturnsTrue() { // Go ref: accounts.go — act.Expires <= tn ⇒ expired, activationExpired fires. var account = new Account("test"); account.RegisterActivation("svc.past", ExpiredClaim("svc.past")); account.IsActivationExpired("svc.past").ShouldBeTrue(); } // --------------------------------------------------------------------------- // GetExpiredActivations // --------------------------------------------------------------------------- [Fact] public void GetExpiredActivations_ReturnsOnlyExpired() { // Go ref: accounts.go — activationExpired is called only for expired claims. var account = new Account("test"); account.RegisterActivation("svc.a", ValidClaim("svc.a")); account.RegisterActivation("svc.b", ExpiredClaim("svc.b")); account.RegisterActivation("svc.c", ValidClaim("svc.c")); account.RegisterActivation("svc.d", ExpiredClaim("svc.d")); var expired = account.GetExpiredActivations(); expired.Count.ShouldBe(2); expired.ShouldContain("svc.b"); expired.ShouldContain("svc.d"); expired.ShouldNotContain("svc.a"); expired.ShouldNotContain("svc.c"); } // --------------------------------------------------------------------------- // RemoveExpiredActivations // --------------------------------------------------------------------------- [Fact] public void RemoveExpiredActivations_RemovesAndReturnsCount() { // Go ref: accounts.go — activationExpired removes the import when activation expires. var account = new Account("test"); account.RegisterActivation("svc.live", ValidClaim("svc.live")); account.RegisterActivation("svc.gone1", ExpiredClaim("svc.gone1")); account.RegisterActivation("svc.gone2", ExpiredClaim("svc.gone2")); var removed = account.RemoveExpiredActivations(); removed.ShouldBe(2); // The expired ones should no longer be found. account.CheckActivationExpiry("svc.gone1").Found.ShouldBeFalse(); account.CheckActivationExpiry("svc.gone2").Found.ShouldBeFalse(); // The live one should still be registered. account.CheckActivationExpiry("svc.live").Found.ShouldBeTrue(); } // --------------------------------------------------------------------------- // ActiveActivationCount // --------------------------------------------------------------------------- [Fact] public void ActiveActivationCount_ExcludesExpired() { // Go ref: accounts.go — only non-expired activations are considered active. var account = new Account("test"); account.RegisterActivation("svc.1", ValidClaim("svc.1")); account.RegisterActivation("svc.2", ValidClaim("svc.2")); account.RegisterActivation("svc.3", ExpiredClaim("svc.3")); account.ActiveActivationCount.ShouldBe(2); } // --------------------------------------------------------------------------- // ActivationClaim.TimeToExpiry // --------------------------------------------------------------------------- [Fact] public void ActivationClaim_TimeToExpiry_Zero_WhenExpired() { // Go ref: accounts.go — expired activation has no remaining time. var claim = ExpiredClaim("svc.expired"); claim.IsExpired.ShouldBeTrue(); claim.TimeToExpiry.ShouldBe(TimeSpan.Zero); } }