Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build/dependencies.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<PropertyGroup>
<AspNetCoreMinSupportedVersion>2.1.1</AspNetCoreMinSupportedVersion>
<BannedApiAnalyzersVersion>3.3.4</BannedApiAnalyzersVersion>
<MicrosoftBclTimeProviderVersion>8.0.1</MicrosoftBclTimeProviderVersion>
<MicrosoftCSharpVersion>4.5.0</MicrosoftCSharpVersion>
<MicrosoftSourceLinkGitHubVersion>1.0.0</MicrosoftSourceLinkGitHubVersion>
<NetStandardVersion>2.0.3</NetStandardVersion>
Expand Down
1 change: 1 addition & 0 deletions build/dependenciesTest.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<BannedApiAnalyzersVersion>3.3.4</BannedApiAnalyzersVersion>
<DotNetCoreAppRuntimeVersion>2.1.30</DotNetCoreAppRuntimeVersion>
<MicrosoftAzureKeyVaultCryptographyVersion>2.0.5</MicrosoftAzureKeyVaultCryptographyVersion>
<MicrosoftExtensionsTimeProviderTestingVersion>8.8.0</MicrosoftExtensionsTimeProviderTestingVersion>
<MicrosoftNETTestSdkVersion>17.11.0</MicrosoftNETTestSdkVersion>
<NetStandardVersion>2.0.3</NetStandardVersion>
<NewtonsoftVersion>13.0.3</NewtonsoftVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
<ProjectReference Include="..\Microsoft.IdentityModel.Tokens\Microsoft.IdentityModel.Tokens.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Bcl.TimeProvider" Version="$(MicrosoftBclTimeProviderVersion)" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,8 @@
<PackageReference Include="System.Text.Json" Version="$(SystemTextJson)" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Bcl.TimeProvider" Version="$(MicrosoftBclTimeProviderVersion)" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ protected ValidationParameters(ValidationParameters other)
RoleClaimTypeRetriever = other.RoleClaimTypeRetriever;
SaveSigninToken = other.SaveSigninToken;
SignatureValidator = other.SignatureValidator;
TimeProvider = other.TimeProvider;
TokenDecryptionKeyResolver = other.TokenDecryptionKeyResolver;
TokenDecryptionKeys = other.TokenDecryptionKeys;
TokenReplayCache = other.TokenReplayCache;
Expand Down Expand Up @@ -446,6 +447,11 @@ public SignatureValidatorDelegate SignatureValidator
set { _signatureValidator = value; }
}

/// <summary>
/// Gets or sets the time provider.
/// </summary>
internal TimeProvider TimeProvider { get; set; } = TimeProvider.System;

/// <summary>
/// Gets or sets a delegate that will be called to retrieve a <see cref="SecurityKey"/> used for decryption.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ internal static ValidationResult<ValidatedSigningKeyLifetime> ValidateIssuerSign
CallContext? callContext)
#pragma warning restore CA1801 // Review unused parameters
{
DateTime utcNow = DateTime.UtcNow;
DateTime utcNow = validationParameters.TimeProvider.GetUtcNow().UtcDateTime;
DateTime? notBeforeUtc = null;
DateTime? notAfterUtc = null;
X509SecurityKey? x509SecurityKey = securityKey as X509SecurityKey;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ internal static ValidationResult<ValidatedLifetime> ValidateLifetime(
new StackFrame(true),
new(NotBeforeDate: notBefore, ExpirationDate: expires));

DateTime utcNow = DateTime.UtcNow;
DateTime utcNow = validationParameters.TimeProvider.GetUtcNow().UtcDateTime;
if (notBefore.HasValue && (notBefore.Value > DateTimeUtil.Add(utcNow, validationParameters.ClockSkew)))
return new LifetimeValidationError(
new MessageDetail(
Expand Down
13 changes: 13 additions & 0 deletions test/Microsoft.IdentityModel.TestUtils/MockTimeProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;

namespace Microsoft.IdentityModel.TestUtils
{
internal class MockTimeProvider : TimeProvider
{
// always return 09/16/2024 00:00:00:00
public override DateTimeOffset GetUtcNow() => new DateTimeOffset(2024, 9, 16, 0, 0, 0, new(0));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,17 @@ public static TheoryData<ValidateLifetimeTheoryData> ValidateLifetimeTestCases
{
get
{
DateTime now = DateTime.UtcNow;
DateTime oneHourFromNow = DateTime.UtcNow.AddHours(1);
DateTime twoHoursFromNow = DateTime.UtcNow.AddHours(2);
DateTime twoMinutesFromNow = DateTime.UtcNow.AddMinutes(2);
DateTime sixMinutesFromNow = DateTime.UtcNow.AddMinutes(6);
DateTime oneHourAgo = DateTime.UtcNow.AddHours(-1);
DateTime twoHoursAgo = DateTime.UtcNow.AddHours(-2);
DateTime twoMinutesAgo = DateTime.UtcNow.AddMinutes(-2);
DateTime oneMinuteAgo = DateTime.UtcNow.AddMinutes(-1);
DateTime sixMinutesAgo = DateTime.UtcNow.AddMinutes(-6);
MockTimeProvider timeProvider = new MockTimeProvider();
DateTime utcNow = timeProvider.GetUtcNow().UtcDateTime;
DateTime oneHourFromNow = utcNow.AddHours(1);
DateTime twoHoursFromNow = utcNow.AddHours(2);
DateTime twoMinutesFromNow = utcNow.AddMinutes(2);
DateTime sixMinutesFromNow = utcNow.AddMinutes(6);
DateTime oneHourAgo = utcNow.AddHours(-1);
DateTime twoHoursAgo = utcNow.AddHours(-2);
DateTime twoMinutesAgo = utcNow.AddMinutes(-2);
DateTime oneMinuteAgo = utcNow.AddMinutes(-1);
DateTime sixMinutesAgo = utcNow.AddMinutes(-6);

return new TheoryData<ValidateLifetimeTheoryData>
{
Expand All @@ -68,27 +69,33 @@ public static TheoryData<ValidateLifetimeTheoryData> ValidateLifetimeTestCases
Expires = oneHourFromNow,
NotBefore = oneHourAgo,
Result = new ValidatedLifetime(oneHourAgo, oneHourFromNow),
ValidationParameters = new ValidationParameters()
ValidationParameters = new ValidationParameters(){TimeProvider = timeProvider }
},
new ValidateLifetimeTheoryData("Valid_NotBeforeIsNull")
{
Expires = oneHourFromNow,
NotBefore = null,
Result = new ValidatedLifetime(null, oneHourFromNow),
ValidationParameters = new ValidationParameters()
ValidationParameters = new ValidationParameters(){ TimeProvider = timeProvider }
},
new ValidateLifetimeTheoryData("Valid_SkewForward")
{
Expires = oneHourFromNow,
NotBefore = twoMinutesFromNow,
ValidationParameters = new ValidationParameters { ClockSkew = TimeSpan.FromMinutes(5) },
ValidationParameters = new ValidationParameters {
ClockSkew = TimeSpan.FromMinutes(5),
TimeProvider = timeProvider
},
Result = new ValidatedLifetime(twoMinutesFromNow, oneHourFromNow),
},
new ValidateLifetimeTheoryData("Valid_SkewBackward")
{
Expires = oneMinuteAgo,
NotBefore = twoMinutesAgo,
ValidationParameters = new ValidationParameters { ClockSkew = TimeSpan.FromMinutes(5) },
ValidationParameters = new ValidationParameters {
ClockSkew = TimeSpan.FromMinutes(5),
TimeProvider = timeProvider
},
Result = new ValidatedLifetime(twoMinutesAgo, oneMinuteAgo),
},
new ValidateLifetimeTheoryData("Invalid_ValidationParametersIsNull")
Expand All @@ -107,7 +114,7 @@ public static TheoryData<ValidateLifetimeTheoryData> ValidateLifetimeTestCases
{
ExpectedException = ExpectedException.SecurityTokenNoExpirationException("IDX10225:"),
NotBefore = oneHourAgo,
ValidationParameters = new ValidationParameters(),
ValidationParameters = new ValidationParameters() { TimeProvider = timeProvider },
Result = new ValidationError(
new MessageDetail(LogMessages.IDX10225, "null"),
ValidationFailureType.LifetimeValidationFailed,
Expand All @@ -119,7 +126,7 @@ public static TheoryData<ValidateLifetimeTheoryData> ValidateLifetimeTestCases
ExpectedException = ExpectedException.SecurityTokenInvalidLifetimeException("IDX10224:"),
Expires = oneHourAgo,
NotBefore = oneHourFromNow,
ValidationParameters = new ValidationParameters(),
ValidationParameters = new ValidationParameters() { TimeProvider = timeProvider },
Result = new ValidationError(
new MessageDetail(
LogMessages.IDX10224,
Expand All @@ -134,12 +141,12 @@ public static TheoryData<ValidateLifetimeTheoryData> ValidateLifetimeTestCases
ExpectedException = ExpectedException.SecurityTokenNotYetValidException("IDX10222:"),
Expires = twoHoursFromNow,
NotBefore = oneHourFromNow,
ValidationParameters = new ValidationParameters(),
ValidationParameters = new ValidationParameters() { TimeProvider = timeProvider },
Result = new ValidationError(
new MessageDetail(
LogMessages.IDX10222,
LogHelper.MarkAsNonPII(oneHourFromNow),
LogHelper.MarkAsNonPII(now)),
LogHelper.MarkAsNonPII(utcNow)),
ValidationFailureType.LifetimeValidationFailed,
typeof(SecurityTokenNotYetValidException),
null),
Expand All @@ -149,12 +156,12 @@ public static TheoryData<ValidateLifetimeTheoryData> ValidateLifetimeTestCases
ExpectedException = ExpectedException.SecurityTokenExpiredException("IDX10223:"),
Expires = oneHourAgo,
NotBefore = twoHoursAgo,
ValidationParameters = new ValidationParameters(),
ValidationParameters = new ValidationParameters() { TimeProvider = timeProvider },
Result = new ValidationError(
new MessageDetail(
LogMessages.IDX10223,
LogHelper.MarkAsNonPII(oneHourAgo),
LogHelper.MarkAsNonPII(now)),
LogHelper.MarkAsNonPII(utcNow)),
ValidationFailureType.LifetimeValidationFailed,
typeof(SecurityTokenExpiredException),
null),
Expand All @@ -164,12 +171,15 @@ public static TheoryData<ValidateLifetimeTheoryData> ValidateLifetimeTestCases
ExpectedException = ExpectedException.SecurityTokenNotYetValidException("IDX10222:"),
Expires = oneHourFromNow,
NotBefore = sixMinutesFromNow,
ValidationParameters = new ValidationParameters { ClockSkew = TimeSpan.FromMinutes(5) },
ValidationParameters = new ValidationParameters {
ClockSkew = TimeSpan.FromMinutes(5),
TimeProvider = timeProvider
},
Result = new ValidationError(
new MessageDetail(
LogMessages.IDX10222,
LogHelper.MarkAsNonPII(sixMinutesFromNow),
LogHelper.MarkAsNonPII(now)),
LogHelper.MarkAsNonPII(utcNow)),
ValidationFailureType.LifetimeValidationFailed,
typeof(SecurityTokenNotYetValidException),
null),
Expand All @@ -179,12 +189,15 @@ public static TheoryData<ValidateLifetimeTheoryData> ValidateLifetimeTestCases
ExpectedException = ExpectedException.SecurityTokenExpiredException("IDX10223:"),
Expires = sixMinutesAgo,
NotBefore = twoHoursAgo,
ValidationParameters = new ValidationParameters { ClockSkew = TimeSpan.FromMinutes(5) },
ValidationParameters = new ValidationParameters {
ClockSkew = TimeSpan.FromMinutes(5),
TimeProvider = timeProvider
},
Result = new ValidationError(
new MessageDetail(
LogMessages.IDX10223,
LogHelper.MarkAsNonPII(sixMinutesAgo),
LogHelper.MarkAsNonPII(now)),
LogHelper.MarkAsNonPII(utcNow)),
ValidationFailureType.LifetimeValidationFailed,
typeof(SecurityTokenExpiredException),
null),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ public static TheoryData<SigningKeyValidationTheoryData> SigningKeyValidationTes
{
get
{
DateTime utcNow = DateTime.UtcNow;
MockTimeProvider timeProvider = new MockTimeProvider();
DateTime utcNow = timeProvider.GetUtcNow().UtcDateTime;
DateTime utcExpired = KeyingMaterial.ExpiredX509SecurityKey_Public.Certificate.NotAfter.ToUniversalTime();
DateTime utcNotYetValid = KeyingMaterial.NotYetValidX509SecurityKey_Public.Certificate.NotBefore.ToUniversalTime();

Expand All @@ -62,7 +63,7 @@ public static TheoryData<SigningKeyValidationTheoryData> SigningKeyValidationTes
TestId = "Valid_SecurityTokenIsPresent",
SecurityKey = KeyingMaterial.SymmetricSecurityKey2_256,
SecurityToken = new JwtSecurityToken(),
ValidationParameters = new ValidationParameters(),
ValidationParameters = new ValidationParameters(){ TimeProvider = timeProvider },
Result = new ValidatedSigningKeyLifetime(null, null, utcNow)
},
new SigningKeyValidationTheoryData
Expand All @@ -71,7 +72,7 @@ public static TheoryData<SigningKeyValidationTheoryData> SigningKeyValidationTes
ExpectedException = ExpectedException.SecurityTokenArgumentNullException(substringExpected: "IDX10253:"),
SecurityKey = null,
SecurityToken = new JwtSecurityToken(),
ValidationParameters = new ValidationParameters(),
ValidationParameters = new ValidationParameters(){ TimeProvider = timeProvider },
Result = new ValidationError(
new MessageDetail(LogMessages.IDX10253),
ValidationFailureType.SigningKeyValidationFailed,
Expand All @@ -84,7 +85,7 @@ public static TheoryData<SigningKeyValidationTheoryData> SigningKeyValidationTes
ExpectedException = ExpectedException.SecurityTokenArgumentNullException(substringExpected: "IDX10000:"),
SecurityKey = KeyingMaterial.SymmetricSecurityKey2_256,
SecurityToken = null,
ValidationParameters = new ValidationParameters (),
ValidationParameters = new ValidationParameters() { TimeProvider = timeProvider },
Result = new ValidationError(
new MessageDetail(
LogMessages.IDX10000,
Expand Down Expand Up @@ -114,7 +115,7 @@ public static TheoryData<SigningKeyValidationTheoryData> SigningKeyValidationTes
ExpectedException = ExpectedException.SecurityTokenInvalidSigningKeyException(substringExpected: "IDX10249:"),
SecurityKey = KeyingMaterial.ExpiredX509SecurityKey_Public,
SecurityToken = new JwtSecurityToken(),
ValidationParameters = new ValidationParameters (),
ValidationParameters = new ValidationParameters() { TimeProvider = timeProvider },
Result = new ValidationError(
new MessageDetail(
LogMessages.IDX10249,
Expand All @@ -130,7 +131,7 @@ public static TheoryData<SigningKeyValidationTheoryData> SigningKeyValidationTes
ExpectedException = ExpectedException.SecurityTokenInvalidSigningKeyException(substringExpected: "IDX10248:"),
SecurityKey = KeyingMaterial.NotYetValidX509SecurityKey_Public,
SecurityToken = new JwtSecurityToken(),
ValidationParameters = new ValidationParameters (),
ValidationParameters = new ValidationParameters() { TimeProvider = timeProvider },
Result = new ValidationError(
new MessageDetail(
LogMessages.IDX10248,
Expand All @@ -146,7 +147,7 @@ public static TheoryData<SigningKeyValidationTheoryData> SigningKeyValidationTes
ExpectedException = ExpectedException.SecurityTokenArgumentNullException("IDX10253:"),
SecurityKey = null,
SecurityToken = new JwtSecurityToken(),
ValidationParameters = new ValidationParameters (),
ValidationParameters = new ValidationParameters() { TimeProvider = timeProvider },
Result = new ValidationError(
new MessageDetail(LogMessages.IDX10253),
ValidationFailureType.SigningKeyValidationFailed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using Xunit;
using Microsoft.IdentityModel.TestUtils;

namespace Microsoft.IdentityModel.Tokens.Tests.Validation
{
Expand Down Expand Up @@ -46,5 +47,25 @@ public void ValidTypes_Get_ReturnsEmptyList()
Assert.Empty(validationParameters.ValidTypes);
Assert.True(validationParameters.ValidTypes is IList<string>);
}

[Fact]
public void Valid_Set_TimeProvider()
{
TimeProvider timeProvider = new MockTimeProvider();
var validationParameters = new ValidationParameters()
{
TimeProvider = timeProvider
};

Assert.Equal(validationParameters.TimeProvider, timeProvider);
}

[Fact]
public void Valid_NotNull_TimeProvider()
{
var validationParameters = new ValidationParameters();

Assert.NotNull(validationParameters.TimeProvider);
}
}
}
Loading