diff --git a/src/Core/Auth/Models/Business/Tokenables/TwoFactorRememberTokenableFactory.cs b/src/Core/Auth/Models/Business/Tokenables/TwoFactorRememberTokenableFactory.cs
index dedab6bb5a85..1fc9e45bdc44 100644
--- a/src/Core/Auth/Models/Business/Tokenables/TwoFactorRememberTokenableFactory.cs
+++ b/src/Core/Auth/Models/Business/Tokenables/TwoFactorRememberTokenableFactory.cs
@@ -14,5 +14,6 @@ public TwoFactorRememberTokenable CreateToken(User user, Device device, string s
{
ExpirationDate = timeProvider.GetUtcNow().UtcDateTime
.AddDays(globalSettings.TwoFactorRememberTokenLifetimeInDays),
+ TimeProvider = timeProvider,
};
}
diff --git a/src/Core/Tokens/ExpiringTokenable.cs b/src/Core/Tokens/ExpiringTokenable.cs
index 5aac7080fc41..c0343cfddd5b 100644
--- a/src/Core/Tokens/ExpiringTokenable.cs
+++ b/src/Core/Tokens/ExpiringTokenable.cs
@@ -14,7 +14,13 @@ public abstract class ExpiringTokenable : Tokenable
///
public override bool Valid => !IsExpired && TokenIsValid();
- public bool IsExpired => ExpirationDate < DateTime.UtcNow;
+ ///
+ /// Clock used for the expiration check. Can be overwritten for tests.
+ ///
+ [JsonIgnore]
+ internal TimeProvider TimeProvider { get; set; } = TimeProvider.System;
+
+ public bool IsExpired => ExpirationDate < TimeProvider.GetUtcNow().UtcDateTime;
///
/// Validates that the token data properties are correct.