ISystemClock is obsolete

Microsoft.AspNetCore.Authentication.ISystemClock has been used by ASP.NET Core's authentication and identity components since version 1.0 to enable unit testing of time-related functionality, like expiration checking. .NET 8 includes a suitable abstraction, System.TimeProvider, that provides the same functionality and much more. We're taking this opportunity to obsolete ISystemClock and replace it with TimeProvider throughout the ASP.NET Core libraries.

Version introduced

ASP.NET Core 8.0 Preview 5

Previous behavior

ISystemClock was injected into the constructors of the authentication and identity components by dependency injection (DI) and could be overridden for testing.

The default SystemClock implementation truncated to the nearest second for easier formatting.

New behavior

ISystemClock, SystemClock, and the authentication handler constructors that have an ISystemClock parameter have been marked obsolete. Using these APIs in code will generate a warning at compile time.

ISystemClock remains in the dependency injection container but is no longer used. It may be removed from the container in a future version.

TimeProvider is now a settable property on the Options classes for the authentication and identity components. It can be set directly or by registering a provider in the dependency injection container.

TimeProvider does not truncate to the nearest second. Consumers are expected to correctly format the time as needed.

Type of breaking change

This change affects source compatibility.

Reason for change

This change was made to unify time abstraction across the stack for easier testing.

If you have components that derive from Microsoft.AspNetCore.Authentication.AuthenticationHandler<TOptions> or Microsoft.AspNetCore.Identity.SecurityStampValidator<TUser>, remove the ISystemClock constructor parameter and call the new base constructor accordingly.

- public BasicAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
-     : base(options, logger, encoder, clock)
+ public BasicAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder)
+     : base(options, logger, encoder)

Similarly, derived implementations that reference the Clock property on these types should reference the new TimeProvider property instead.

- var currentUtc = Clock.UtcNow;
+ var currentUtc = TimeProvider.GetUtcNow();

You can set TimeProvider for testing on the options or via DI.

Affected APIs