From 4067f673a05d4eee046fc5a09ee96b62fa27fc75 Mon Sep 17 00:00:00 2001 From: Franco Fung Date: Tue, 13 Aug 2024 09:08:45 -0700 Subject: [PATCH 01/32] Adding benchmark for new ValidateTokenAsync model vs old. --- .../ValidateTokenAsyncWithVPTests.cs | 86 +++++++++++++++++++ .../Properties/AssemblyInfo.cs | 1 + 2 files changed, 87 insertions(+) create mode 100644 benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithVPTests.cs diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithVPTests.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithVPTests.cs new file mode 100644 index 0000000000..ca402f1305 --- /dev/null +++ b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithVPTests.cs @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; +using Microsoft.IdentityModel.JsonWebTokens; +using Microsoft.IdentityModel.Tokens; + +namespace Microsoft.IdentityModel.Benchmarks +{ + // dotnet run -c release -f net8.0 --filter Microsoft.IdentityModel.Benchmarks.ValidateTokenAsyncWithVPTests* + + public class ValidateTokenAsyncWithVPTests + { + private CallContext _callContext; + private JsonWebTokenHandler _jsonWebTokenHandler; + private SecurityTokenDescriptor _tokenDescriptor; + private SecurityTokenDescriptor _tokenDescriptorExtendedClaims; + private string _jws; + private string _jwsExtendedClaims; + private TokenValidationParameters _tokenValidationParameters; //TODO:Add additional test to compare with ValidationParameters also use clone for perf. + private ValidationParameters _validationParameters; + + [GlobalSetup] + public void Setup() + { + _tokenDescriptor = new SecurityTokenDescriptor + { + Claims = BenchmarkUtils.Claims, + SigningCredentials = BenchmarkUtils.SigningCredentialsRsaSha256, + }; + + _tokenDescriptorExtendedClaims = new SecurityTokenDescriptor + { + Claims = BenchmarkUtils.ClaimsExtendedExample, + SigningCredentials = BenchmarkUtils.SigningCredentialsRsaSha256, + }; + + _jsonWebTokenHandler = new JsonWebTokenHandler(); + _jws = _jsonWebTokenHandler.CreateToken(_tokenDescriptor); + _jwsExtendedClaims = _jsonWebTokenHandler.CreateToken(_tokenDescriptorExtendedClaims); + + _validationParameters = new ValidationParameters(); + _validationParameters.ValidAudiences.Add(BenchmarkUtils.Audience); + _validationParameters.ValidIssuers.Add(BenchmarkUtils.Issuer); + _validationParameters.IssuerSigningKeys.Add(BenchmarkUtils.SigningCredentialsRsaSha256.Key); + + _callContext = new CallContext(); + + _tokenValidationParameters = new TokenValidationParameters() + { + ValidAudience = BenchmarkUtils.Audience, + ValidateLifetime = true, + ValidIssuer = BenchmarkUtils.Issuer, + IssuerSigningKey = BenchmarkUtils.SigningCredentialsRsaSha256.Key, + }; + } + + [Benchmark] + public async Task> JsonWebTokenHandler_ValidateTokenAsyncWithVP_CreateClaims() + { + var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + var claimsIdentity = result.ClaimsIdentity; + var claims = claimsIdentity.Claims; + return claims.ToList(); + } + + [Benchmark] + public async Task> JsonWebTokenHandler_ValidateTokenAsync_CreateClaims() + { + var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); + var claimsIdentity = result.ClaimsIdentity; + var claims = claimsIdentity.Claims; + return claims.ToList(); + } + + [Benchmark] + public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + + [Benchmark] + public async Task JsonWebTokenHandler_ValidateTokenAsync() => await _jsonWebTokenHandler.ValidateTokenAsync(_jws, _tokenValidationParameters).ConfigureAwait(false); + } +} diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/Properties/AssemblyInfo.cs b/src/Microsoft.IdentityModel.JsonWebTokens/Properties/AssemblyInfo.cs index 9ec5a0543e..4b6c640a87 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/Properties/AssemblyInfo.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/Properties/AssemblyInfo.cs @@ -18,3 +18,4 @@ [assembly: InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tokens, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tokens.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] +[assembly: InternalsVisibleTo("Microsoft.IdentityModel.Benchmarks, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] From ea1c1be2492df83347d1a0afb82bde859417099a Mon Sep 17 00:00:00 2001 From: Franco Fung <38921563+FuPingFranco@users.noreply.github.com> Date: Tue, 13 Aug 2024 10:28:19 -0700 Subject: [PATCH 02/32] Update benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithVPTests.cs Co-authored-by: Keegan Caruso --- .../ValidateTokenAsyncWithVPTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithVPTests.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithVPTests.cs index ca402f1305..129f83f665 100644 --- a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithVPTests.cs +++ b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithVPTests.cs @@ -81,6 +81,6 @@ public async Task> JsonWebTokenHandler_ValidateTokenAsync_CreateClai public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); [Benchmark] - public async Task JsonWebTokenHandler_ValidateTokenAsync() => await _jsonWebTokenHandler.ValidateTokenAsync(_jws, _tokenValidationParameters).ConfigureAwait(false); + public async Task JsonWebTokenHandler_ValidateTokenAsync() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); } } From a7d26802576d2d11c0f3481199f6c583a4ea25aa Mon Sep 17 00:00:00 2001 From: Franco Fung Date: Wed, 14 Aug 2024 11:39:44 -0700 Subject: [PATCH 03/32] Updated class naming to be more explicit and added benchmark using clone --- ...okenAsyncWithValidationParametersTests.cs} | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) rename benchmark/Microsoft.IdentityModel.Benchmarks/{ValidateTokenAsyncWithVPTests.cs => ValidateTokenAsyncWithValidationParametersTests.cs} (73%) diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithVPTests.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs similarity index 73% rename from benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithVPTests.cs rename to benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs index 129f83f665..7bd5e999cf 100644 --- a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithVPTests.cs +++ b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs @@ -11,9 +11,9 @@ namespace Microsoft.IdentityModel.Benchmarks { - // dotnet run -c release -f net8.0 --filter Microsoft.IdentityModel.Benchmarks.ValidateTokenAsyncWithVPTests* + // dotnet run -c release -f net8.0 --filter Microsoft.IdentityModel.Benchmarks.ValidateTokenAsyncWithValidationParametersTests* - public class ValidateTokenAsyncWithVPTests + public class ValidateTokenAsyncWithValidationParametersTests { private CallContext _callContext; private JsonWebTokenHandler _jsonWebTokenHandler; @@ -21,7 +21,7 @@ public class ValidateTokenAsyncWithVPTests private SecurityTokenDescriptor _tokenDescriptorExtendedClaims; private string _jws; private string _jwsExtendedClaims; - private TokenValidationParameters _tokenValidationParameters; //TODO:Add additional test to compare with ValidationParameters also use clone for perf. + private TokenValidationParameters _tokenValidationParameters; private ValidationParameters _validationParameters; [GlobalSetup] @@ -60,7 +60,7 @@ public void Setup() } [Benchmark] - public async Task> JsonWebTokenHandler_ValidateTokenAsyncWithVP_CreateClaims() + public async Task> JsonWebTokenHandler_ValidateTokenAsyncWithValidationParameters_CreateClaims() { var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); var claimsIdentity = result.ClaimsIdentity; @@ -69,7 +69,7 @@ public async Task> JsonWebTokenHandler_ValidateTokenAsyncWithVP_Crea } [Benchmark] - public async Task> JsonWebTokenHandler_ValidateTokenAsync_CreateClaims() + public async Task> JsonWebTokenHandler_ValidateTokenAsyncWithTokenValidationParameters_CreateClaims() { var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); var claimsIdentity = result.ClaimsIdentity; @@ -78,9 +78,19 @@ public async Task> JsonWebTokenHandler_ValidateTokenAsync_CreateClai } [Benchmark] - public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + public async Task JsonWebTokenHandler_ValidateTokenAsyncWithValidationParameters() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); [Benchmark] - public async Task JsonWebTokenHandler_ValidateTokenAsync() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); + public async Task JsonWebTokenHandler_ValidateTokenAsyncWithTokenValidationParameters() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); + + [Benchmark] + public async Task JsonWebTokenHandler_ValidateTokenAsyncWithTokenValidationParametersUsingClone() + { + var tokenValidationParameters = _tokenValidationParameters.Clone(); + tokenValidationParameters.ValidIssuer = "different-issuer"; + tokenValidationParameters.ValidAudience = "different-audience"; + tokenValidationParameters.ValidateLifetime = false; + return await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, tokenValidationParameters).ConfigureAwait(false); + } } } From 4f80ff75d2f86413201a6b64289e66828822a72f Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Fri, 16 Aug 2024 15:28:51 +0100 Subject: [PATCH 04/32] Added benchmarks to compare performance on multiple validation scenarios --- ...TokenAsyncWithValidationParametersTests.cs | 116 +++++++++++++++--- 1 file changed, 96 insertions(+), 20 deletions(-) diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs index 7bd5e999cf..2b916594d1 100644 --- a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs +++ b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs @@ -8,12 +8,13 @@ using BenchmarkDotNet.Attributes; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; +using System; namespace Microsoft.IdentityModel.Benchmarks { - // dotnet run -c release -f net8.0 --filter Microsoft.IdentityModel.Benchmarks.ValidateTokenAsyncWithValidationParametersTests* + // dotnet run -c release -f net8.0 --filter Microsoft.IdentityModel.Benchmarks.ValidateTokenAsyncWithVPTests* - public class ValidateTokenAsyncWithValidationParametersTests + public class ValidateTokenAsyncWithVPTests { private CallContext _callContext; private JsonWebTokenHandler _jsonWebTokenHandler; @@ -23,6 +24,8 @@ public class ValidateTokenAsyncWithValidationParametersTests private string _jwsExtendedClaims; private TokenValidationParameters _tokenValidationParameters; private ValidationParameters _validationParameters; + private TokenValidationParameters _invalidTokenValidationParameters; + private ValidationParameters _invalidValidationParameters; [GlobalSetup] public void Setup() @@ -48,6 +51,10 @@ public void Setup() _validationParameters.ValidIssuers.Add(BenchmarkUtils.Issuer); _validationParameters.IssuerSigningKeys.Add(BenchmarkUtils.SigningCredentialsRsaSha256.Key); + _invalidValidationParameters = new ValidationParameters(); + _invalidValidationParameters.ValidAudiences.Add(BenchmarkUtils.Audience); + _invalidValidationParameters.ValidIssuers.Add(BenchmarkUtils.Issuer); + _callContext = new CallContext(); _tokenValidationParameters = new TokenValidationParameters() @@ -56,41 +63,110 @@ public void Setup() ValidateLifetime = true, ValidIssuer = BenchmarkUtils.Issuer, IssuerSigningKey = BenchmarkUtils.SigningCredentialsRsaSha256.Key, + ValidateIssuerSigningKey = true, + ValidateTokenReplay = true, + RequireSignedTokens = true, + ValidateSignatureLast = true + }; + + _invalidTokenValidationParameters = new TokenValidationParameters() + { + ValidAudience = BenchmarkUtils.Audience, + ValidateLifetime = true, + ValidIssuer = BenchmarkUtils.Issuer, + ValidateIssuerSigningKey = true, + ValidateTokenReplay = true, + ValidateSignatureLast = true }; } [Benchmark] - public async Task> JsonWebTokenHandler_ValidateTokenAsyncWithValidationParameters_CreateClaims() + public async Task JsonWebTokenHandler_01_ValidateTokenAsyncWithTVP() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); + + [Benchmark] + public async Task JsonWebTokenHandler_02_ValidateTokenAsyncWithTVPUsingClone() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false); + + [Benchmark] + public async Task JsonWebTokenHandler_03_ValidateTokenAsyncWithVP() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + + [Benchmark] + public async Task JsonWebTokenHandler_04_ValidateTokenAsyncWithTVP_SucceedOnThirdAttempt() { - var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); - var claimsIdentity = result.ClaimsIdentity; - var claims = claimsIdentity.Claims; - return claims.ToList(); + TokenValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); + + return result; } [Benchmark] - public async Task> JsonWebTokenHandler_ValidateTokenAsyncWithTokenValidationParameters_CreateClaims() + public async Task JsonWebTokenHandler_05_ValidateTokenAsyncWithTVPUsingClone_SucceedOnThirdAttempt() { - var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); - var claimsIdentity = result.ClaimsIdentity; - var claims = claimsIdentity.Claims; - return claims.ToList(); + TokenValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false); + + return result; } [Benchmark] - public async Task JsonWebTokenHandler_ValidateTokenAsyncWithValidationParameters() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + public async Task JsonWebTokenHandler_06_ValidateTokenAsyncWithVP_SucceedOnThirdAttempt() + { + var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); + return await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + } [Benchmark] - public async Task JsonWebTokenHandler_ValidateTokenAsyncWithTokenValidationParameters() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); + public async Task JsonWebTokenHandler_07_ValidateTokenAsyncWithTVP_SucceedOnFifthAttempt() + { + TokenValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); + + return result; + } + + [Benchmark] + public async Task JsonWebTokenHandler_08_ValidateTokenAsyncWithTVPUsingClone_SucceedOnFifthAttempt() + { + TokenValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false); + + return result; + } + + [Benchmark] + public async Task JsonWebTokenHandler_09_ValidateTokenAsyncWithVP_SucceedOnFifthAttempt() + { + var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); + return await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + } [Benchmark] - public async Task JsonWebTokenHandler_ValidateTokenAsyncWithTokenValidationParametersUsingClone() + public async Task> JsonWebTokenHandler_10_ValidateTokenAsyncWithTVP_CreateClaims() { - var tokenValidationParameters = _tokenValidationParameters.Clone(); - tokenValidationParameters.ValidIssuer = "different-issuer"; - tokenValidationParameters.ValidAudience = "different-audience"; - tokenValidationParameters.ValidateLifetime = false; - return await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, tokenValidationParameters).ConfigureAwait(false); + var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false); + var claimsIdentity = result.ClaimsIdentity; + var claims = claimsIdentity.Claims; + return claims.ToList(); + } + + [Benchmark] + public async Task> JsonWebTokenHandler_11_ValidateTokenAsyncWithVP_CreateClaims() + { + var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + var claimsIdentity = result.ClaimsIdentity; + var claims = claimsIdentity.Claims; + return claims.ToList(); } } } From ae58f1b375ba457e8f173ff427afa55e999b1dde Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Fri, 16 Aug 2024 18:26:23 +0100 Subject: [PATCH 05/32] Removed StackFrame from ValidationResult Adding Result and Unit type. Experiment around allocations and performance. --- .../Result.cs | 133 ++++++++++++++++++ .../Unit.cs | 16 +++ .../JsonWebTokenHandler.DecryptToken.cs | 21 ++- .../JsonWebTokenHandler.ReadToken.cs | 34 ++--- .../JsonWebTokenHandler.ValidateSignature.cs | 31 ++-- ...nWebTokenHandler.ValidateToken.Internal.cs | 34 +++-- .../JwtTokenUtilities.DecryptTokenResult.cs | 24 ++-- .../JwtTokenUtilities.cs | 10 +- ...oft.IdentityModel.LoggingExtensions.csproj | 2 +- .../TokenUtilities.cs | 26 ++-- .../Results/Details/ExceptionDetail.cs | 82 ++++------- .../Results/Details/MessageDetail.cs | 2 +- .../Results/InternalTokenValidationResult.cs | 9 +- .../Results/SignatureValidationResult.cs | 6 +- .../Results/TokenValidationError.cs | 41 ++++++ .../Validation/ValidationParameters.cs | 7 +- .../Validation/Validators.Algorithm.cs | 7 +- .../Validation/Validators.Audience.cs | 13 +- .../Validation/Validators.Issuer.cs | 41 +++--- .../Validation/Validators.IssuerSigningKey.cs | 28 ++-- .../Validation/Validators.Lifetime.cs | 16 +-- .../Validation/Validators.TokenReplay.cs | 19 +-- .../Validation/Validators.TokenType.cs | 22 ++- .../UnitTests.cs | 19 +++ .../JsonWebTokenHandler.DecryptTokenTests.cs | 10 +- .../JsonWebTokenHandler.ReadTokenTests.cs | 9 +- ...nWebTokenHandler.ValidateSignatureTests.cs | 18 +-- .../AlgorithmValidationResultTests.cs | 6 +- .../AudienceValidationResultTests.cs | 34 ++--- .../Validation/ExceptionDetailsTests.cs | 8 +- .../Validation/IssuerValidationResultTests.cs | 8 +- .../LifetimeValidationResultTests.cs | 7 - .../Validation/ReplayValidationResultTests.cs | 6 - .../SigningKeyValidationResultTests.cs | 18 +-- .../TokenTypeValidationResultTests.cs | 16 +-- 35 files changed, 436 insertions(+), 347 deletions(-) create mode 100644 src/Microsoft.IdentityModel.Abstractions/Result.cs create mode 100644 src/Microsoft.IdentityModel.Abstractions/Unit.cs create mode 100644 src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs create mode 100644 test/Microsoft.IdentityModel.Abstractions.Tests/UnitTests.cs diff --git a/src/Microsoft.IdentityModel.Abstractions/Result.cs b/src/Microsoft.IdentityModel.Abstractions/Result.cs new file mode 100644 index 0000000000..c45f0b80e7 --- /dev/null +++ b/src/Microsoft.IdentityModel.Abstractions/Result.cs @@ -0,0 +1,133 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +#nullable enable +namespace Microsoft.IdentityModel.Abstractions +{ + /// + /// Represents a result that can be either successful or unsuccessful. + /// + /// + /// + public readonly struct Result : IEquatable> + { + readonly TResult? _result; + readonly TError? _error; + + /// + /// Creates a successful result. + /// + /// The value associated with the success. + public Result(TResult result) + { + _result = result; + _error = default; + IsSuccess = true; + } + + /// + /// Creates an error result. + /// + /// The error associated with the failure. + public Result(TError error) + { + _result = default; + _error = error; + IsSuccess = false; + } + + /// + /// Gets a value indicating whether the result is successful. + /// + readonly public bool IsSuccess { get; } + + /// + /// Unwraps the result. + /// + /// The wrapped result value. + /// This method is only valid if the result type is successful. + /// Thrown if attempted to unwrap the value from a failed result. + public TResult Unwrap() => IsSuccess ? _result! : throw new InvalidOperationException("Cannot unwrap error result"); + + /// + /// Unwraps the error. + /// + /// The wrapped error value. + /// This method is only valid if the result type is unsuccessful. + /// Thrown if attempted to unwrap an error from a successful result. + public TError UnwrapError() => IsSuccess ? throw new InvalidOperationException("Cannot unwrap success result") : _error!; + + /// + /// + /// + /// + /// + public override bool Equals(object? obj) + { + if (obj is Result other) + { + return Equals(other); + } + + return false; + } + + /// + /// + /// + /// + /// + public override int GetHashCode() + { + if (IsSuccess) + { + return _result!.GetHashCode(); + } + else + { + return _error!.GetHashCode(); + } + } + + /// + /// + /// + /// + /// + /// + public static bool operator ==(Result left, Result right) + { + return left.Equals(right); + } + + /// + /// + /// + /// + /// + /// + public static bool operator !=(Result left, Result right) + { + return !(left == right); + } + + /// + /// + /// + /// + /// + public bool Equals(Result other) + { + if (other.IsSuccess != IsSuccess) + return false; + + if (IsSuccess) + return _result!.Equals(other._result); + else + return _error!.Equals(other._error); + } + } +} +#nullable restore diff --git a/src/Microsoft.IdentityModel.Abstractions/Unit.cs b/src/Microsoft.IdentityModel.Abstractions/Unit.cs new file mode 100644 index 0000000000..6132dc50f0 --- /dev/null +++ b/src/Microsoft.IdentityModel.Abstractions/Unit.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.IdentityModel.Abstractions +{ + /// + /// Unit type used to represent the absence of a specific value. + /// + public record struct Unit + { + /// + /// Returns the default instance of . + /// + public static Unit Default { get; } + } +} diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs index 437d0d692a..3bc83fdd96 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using Microsoft.IdentityModel.Abstractions; +//using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Tokens; using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages; @@ -47,8 +47,7 @@ internal TokenDecryptionResult DecryptToken( ValidationFailureType.TokenDecryptionFailed, new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10612), - ExceptionDetail.ExceptionType.SecurityToken, - new System.Diagnostics.StackFrame())); + ValidationErrorType.SecurityToken)); var keysOrExceptionDetail = GetContentEncryptionKeys(jwtToken, validationParameters, configuration, callContext); if (keysOrExceptionDetail.Item2 != null) // ExceptionDetail returned @@ -66,8 +65,7 @@ internal TokenDecryptionResult DecryptToken( new MessageDetail( TokenLogMessages.IDX10609, LogHelper.MarkAsSecurityArtifact(jwtToken, JwtTokenUtilities.SafeLogJwtToken)), - ExceptionDetail.ExceptionType.SecurityTokenDecryptionFailed, - new System.Diagnostics.StackFrame())); + ValidationErrorType.SecurityTokenDecryptionFailed)); return JwtTokenUtilities.DecryptJwtToken( jwtToken, @@ -97,14 +95,16 @@ internal TokenDecryptionResult DecryptToken( var key = ResolveTokenDecryptionKey(jwtToken.EncodedToken, jwtToken, validationParameters, callContext); if (key != null) { - if (LogHelper.IsEnabled(EventLogLevel.Informational)) - LogHelper.LogInformation(TokenLogMessages.IDX10904, key); + // TODO: Move to CallContext + //if (LogHelper.IsEnabled(EventLogLevel.Informational)) + // LogHelper.LogInformation(TokenLogMessages.IDX10904, key); } else if (configuration != null) { key = ResolveTokenDecryptionKeyFromConfig(jwtToken, configuration); - if (key != null && LogHelper.IsEnabled(EventLogLevel.Informational)) - LogHelper.LogInformation(TokenLogMessages.IDX10905, key); + // TODO: Move to CallContext + //if (key != null && LogHelper.IsEnabled(EventLogLevel.Informational)) + // LogHelper.LogInformation(TokenLogMessages.IDX10905, key); } if (key != null) @@ -202,8 +202,7 @@ internal TokenDecryptionResult DecryptToken( keysAttempted?.ToString() ?? "", exceptionStrings?.ToString() ?? "", LogHelper.MarkAsSecurityArtifact(jwtToken, JwtTokenUtilities.SafeLogJwtToken)), - ExceptionDetail.ExceptionType.SecurityTokenKeyWrap, - new System.Diagnostics.StackFrame()); + ValidationErrorType.SecurityTokenKeyWrap); return (null, exceptionDetail); } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs index f18ce31dcf..8b389f486c 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Tokens; using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages; @@ -21,7 +22,7 @@ public partial class JsonWebTokenHandler : TokenHandler /// returned if is null or empty. /// returned if the validationParameters.TokenReader delegate is not able to parse/read the token as a valid . /// returned if is not a valid JWT, . - internal static TokenReadingResult ReadToken( + internal static Result ReadToken( string token, #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging CallContext? callContext) @@ -29,34 +30,27 @@ internal static TokenReadingResult ReadToken( { if (String.IsNullOrEmpty(token)) { - return new TokenReadingResult( - token, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - TokenLogMessages.IDX10000, - LogHelper.MarkAsNonPII(nameof(token))), - ExceptionDetail.ExceptionType.ArgumentNull, - new System.Diagnostics.StackFrame())); + return new(new TokenValidationError( + ValidationErrorType.Unknown, + new MessageDetail( + TokenLogMessages.IDX10000, + LogHelper.MarkAsNonPII(nameof(token))), + 0x123123)); } try { JsonWebToken jsonWebToken = new JsonWebToken(token); - return new TokenReadingResult(jsonWebToken, token); + return new(jsonWebToken); } #pragma warning disable CA1031 // Do not catch general exception types - catch (Exception ex) + catch #pragma warning restore CA1031 // Do not catch general exception types { - return new TokenReadingResult( - token, - ValidationFailureType.TokenReadingFailed, - new ExceptionDetail( - new MessageDetail(LogMessages.IDX14107), - ExceptionDetail.ExceptionType.SecurityTokenMalformed, - new System.Diagnostics.StackFrame(), - ex)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenMalformed, + new MessageDetail(LogMessages.IDX14107), + Tag: 0x123456)); } } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs index 6b5f36436e..4ad91e92d1 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Text; using Microsoft.IdentityModel.JsonWebTokens.Results; @@ -55,8 +54,7 @@ internal static SignatureValidationResult ValidateSignature( jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken) ), - ExceptionDetail.ExceptionType.SecurityTokenInvalidSignature, - new StackFrame())); + ValidationErrorType.SecurityTokenInvalidSignature)); SecurityKey? key = null; if (validationParameters.IssuerSigningKeyResolver is not null) @@ -93,8 +91,7 @@ internal static SignatureValidationResult ValidateSignature( ValidationFailureType.SignatureValidationFailed, new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10500), - ExceptionDetail.ExceptionType.SecurityTokenSignatureKeyNotFound, - new StackFrame())); + ValidationErrorType.SecurityTokenSignatureKeyNotFound)); } private static SignatureValidationResult ValidateSignatureUsingAllKeys( @@ -130,8 +127,7 @@ private static SignatureValidationResult ValidateSignatureUsingAllKeys( ValidationFailureType.SignatureValidationFailed, new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10500), - ExceptionDetail.ExceptionType.SecurityTokenSignatureKeyNotFound, - new StackFrame())); + ValidationErrorType.SecurityTokenSignatureKeyNotFound)); StringBuilder exceptionStrings = new(); StringBuilder keysAttempted = new(); @@ -215,8 +211,7 @@ private static SignatureValidationResult ValidateSignatureWithKey( LogMessages.IDX14000, LogHelper.MarkAsNonPII(jsonWebToken.Alg), key), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAlgorithm, - new StackFrame())); + ValidationErrorType.SecurityTokenInvalidAlgorithm)); } AlgorithmValidationResult result = validationParameters.AlgorithmValidator( @@ -240,8 +235,7 @@ private static SignatureValidationResult ValidateSignatureWithKey( new MessageDetail(TokenLogMessages.IDX10636, key?.ToString() ?? "Null", LogHelper.MarkAsNonPII(jsonWebToken.Alg)), - ExceptionDetail.ExceptionType.InvalidOperation, - new StackFrame())); + ValidationErrorType.InvalidOperation)); bool valid = EncodingUtils.PerformEncodingDependentOperation( jsonWebToken.EncodedToken, @@ -260,8 +254,7 @@ private static SignatureValidationResult ValidateSignatureWithKey( ValidationFailureType.SignatureValidationFailed, new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10504), - ExceptionDetail.ExceptionType.SecurityTokenInvalidSignature, - new StackFrame())); + ValidationErrorType.SecurityTokenInvalidSignature)); } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) @@ -271,8 +264,7 @@ private static SignatureValidationResult ValidateSignatureWithKey( ValidationFailureType.SignatureValidationFailed, new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10504, ex.ToString()), - ExceptionDetail.ExceptionType.SecurityTokenInvalidSignature, - new StackFrame(), + ValidationErrorType.SecurityTokenInvalidSignature, ex)); } finally @@ -311,8 +303,7 @@ private static ExceptionDetail GetSignatureValidationFailureExceptionDetails( LogHelper.MarkAsNonPII(jwtToken.Kid), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - ExceptionDetail.ExceptionType.SecurityTokenSignatureKeyNotFound, - new StackFrame()); + ValidationErrorType.SecurityTokenSignatureKeyNotFound); } if (kidExists) @@ -325,8 +316,7 @@ private static ExceptionDetail GetSignatureValidationFailureExceptionDetails( LogHelper.MarkAsNonPII(numKeysInConfiguration), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - ExceptionDetail.ExceptionType.SecurityTokenSignatureKeyNotFound, - new StackFrame()); + ValidationErrorType.SecurityTokenSignatureKeyNotFound); return new ExceptionDetail( new MessageDetail( @@ -336,8 +326,7 @@ private static ExceptionDetail GetSignatureValidationFailureExceptionDetails( LogHelper.MarkAsNonPII(numKeysInConfiguration), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - ExceptionDetail.ExceptionType.SecurityTokenSignatureKeyNotFound, - new StackFrame()); + ValidationErrorType.SecurityTokenSignatureKeyNotFound); } private static void PopulateFailedResults( diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs index 675425fc7d..487b3da597 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs @@ -49,18 +49,20 @@ internal async Task ValidateTokenAsync( if (token.Length > MaximumTokenSizeInBytes) return new TokenValidationResult { Exception = LogHelper.LogExceptionMessage(new ArgumentException(LogHelper.FormatInvariant(TokenLogMessages.IDX10209, LogHelper.MarkAsNonPII(token.Length), LogHelper.MarkAsNonPII(MaximumTokenSizeInBytes)))), IsValid = false }; - TokenReadingResult tokenReadingResult = ReadToken(token, callContext); - if (tokenReadingResult.IsValid) + Result result = ReadToken(token, callContext); + if (result.IsSuccess) return await ValidateTokenAsync( - tokenReadingResult.SecurityToken(), + result.Unwrap(), validationParameters, callContext, cancellationToken) .ConfigureAwait(false); + ExceptionDetail exceptionDetail = new ExceptionDetail(result.UnwrapError().MessageDetail, result.UnwrapError().ErrorType); + return new TokenValidationResult { - Exception = tokenReadingResult.Exception, + Exception = exceptionDetail.GetException(), IsValid = false }; } @@ -158,7 +160,7 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration, { validationParameters.RefreshBeforeValidation = false; validationParameters.ValidateWithLKG = true; - ExceptionDetail.ExceptionType recoverableExceptionType = result.ExceptionDetail.Type; + ValidationErrorType recoverableExceptionType = result.ExceptionDetail.Type; BaseConfiguration[] validConfigurations = validationParameters.ConfigurationManager.GetValidLkgConfigurations(); for (int i = 0; i < validConfigurations.Length; i++) @@ -194,11 +196,14 @@ private async ValueTask ValidateJWEAsync( if (!internalResult.AddResult(decryptionResult)) return internalResult; - TokenReadingResult readingResult = ReadToken(decryptionResult.DecryptedToken(), callContext); - if (!internalResult.AddResult(readingResult)) + Result result = ReadToken(decryptionResult.DecryptedToken(), callContext); + if (!result.IsSuccess) return internalResult; + //TokenReadingResult readingResult = ReadToken(decryptionResult.DecryptedToken(), callContext); + //if (!internalResult.AddResult(readingResult)) + // return internalResult; - JsonWebToken decryptedToken = readingResult.SecurityToken() as JsonWebToken; + JsonWebToken decryptedToken = result.Unwrap() as JsonWebToken; InternalTokenValidationResult jwsResult = await ValidateJWSAsync(decryptedToken, validationParameters, configuration, callContext, cancellationToken) @@ -251,11 +256,11 @@ private async ValueTask ValidateJWSAsync( // actor validation if (validationParameters.ValidateActor && !string.IsNullOrWhiteSpace(jsonWebToken.Actor)) { - TokenReadingResult actorReadingResult = ReadToken(jsonWebToken.Actor, callContext); - if (!internalResult.AddResult(actorReadingResult)) + Result actorReadingResult = ReadToken(jsonWebToken.Actor, callContext); + if (!actorReadingResult.IsSuccess) return internalResult; - JsonWebToken actorToken = actorReadingResult.SecurityToken() as JsonWebToken; + JsonWebToken actorToken = actorReadingResult.Unwrap() as JsonWebToken; ValidationParameters actorParameters = validationParameters.ActorValidationParameters; InternalTokenValidationResult actorValidationResult = await ValidateJWSAsync(actorToken, actorParameters, configuration, callContext, cancellationToken) @@ -293,13 +298,14 @@ private static async Task GetCurrentConfigurationAsync(Valida currentConfiguration = await validationParameters.ConfigurationManager.GetBaseConfigurationAsync(CancellationToken.None).ConfigureAwait(false); } #pragma warning disable CA1031 // Do not catch general exception types - catch (Exception ex) + catch #pragma warning restore CA1031 // Do not catch general exception types { // The exception is tracked and dismissed as the ValidationParameters may have the issuer // and signing key set directly on them, allowing the library to continue with token validation. - if (LogHelper.IsEnabled(EventLogLevel.Warning)) - LogHelper.LogWarning(LogHelper.FormatInvariant(TokenLogMessages.IDX10261, validationParameters.ConfigurationManager.MetadataAddress, ex.ToString())); + // TODO: Move to CallContext. + //if (LogHelper.IsEnabled(EventLogLevel.Warning)) + // LogHelper.LogWarning(LogHelper.FormatInvariant(TokenLogMessages.IDX10261, validationParameters.ConfigurationManager.MetadataAddress, ex.ToString())); } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs index 4b300e8aa2..b64095a788 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs @@ -4,10 +4,9 @@ using System; using System.Text; using Microsoft.IdentityModel.Tokens; -using Microsoft.IdentityModel.Logging; -using Microsoft.IdentityModel.Abstractions; +//using Microsoft.IdentityModel.Logging; +//using Microsoft.IdentityModel.Abstractions; using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages; -using System.Diagnostics; namespace Microsoft.IdentityModel.JsonWebTokens { @@ -35,8 +34,7 @@ internal static TokenDecryptionResult DecryptJwtToken( new MessageDetail( TokenLogMessages.IDX10000, nameof(validationParameters)), - ExceptionDetail.ExceptionType.ArgumentNull, - new System.Diagnostics.StackFrame())); + ValidationErrorType.ArgumentNull)); if (decryptionParameters == null) return new TokenDecryptionResult( @@ -46,8 +44,7 @@ internal static TokenDecryptionResult DecryptJwtToken( new MessageDetail( TokenLogMessages.IDX10000, nameof(decryptionParameters)), - ExceptionDetail.ExceptionType.ArgumentNull, - new System.Diagnostics.StackFrame())); + ValidationErrorType.ArgumentNull)); bool decryptionSucceeded = false; bool algorithmNotSupportedByCryptoProvider = false; @@ -62,8 +59,9 @@ internal static TokenDecryptionResult DecryptJwtToken( var cryptoProviderFactory = validationParameters.CryptoProviderFactory ?? key.CryptoProviderFactory; if (cryptoProviderFactory == null) { - if (LogHelper.IsEnabled(EventLogLevel.Warning)) - LogHelper.LogWarning(TokenLogMessages.IDX10607, key); + // TODO: Move to CallContext + //if (LogHelper.IsEnabled(EventLogLevel.Warning)) + // LogHelper.LogWarning(TokenLogMessages.IDX10607, key); continue; } @@ -72,8 +70,9 @@ internal static TokenDecryptionResult DecryptJwtToken( { if (!cryptoProviderFactory.IsSupportedAlgorithm(jsonWebToken.Enc, key)) { - if (LogHelper.IsEnabled(EventLogLevel.Warning)) - LogHelper.LogWarning(TokenLogMessages.IDX10611, LogHelper.MarkAsNonPII(decryptionParameters.Enc), key); + //TODO: Move to CallContext + //if (LogHelper.IsEnabled(EventLogLevel.Warning)) + // LogHelper.LogWarning(TokenLogMessages.IDX10611, LogHelper.MarkAsNonPII(decryptionParameters.Enc), key); algorithmNotSupportedByCryptoProvider = true; continue; @@ -142,8 +141,7 @@ internal static TokenDecryptionResult DecryptJwtToken( new MessageDetail( TokenLogMessages.IDX10679, zipAlgorithm), - ExceptionDetail.ExceptionType.SecurityTokenDecompressionFailed, - new StackFrame(), + ValidationErrorType.SecurityTokenDecompressionFailed, ex)); } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs index dfcd751d5f..81f9fa944b 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Diagnostics; using System.Globalization; using System.Security.Claims; using System.Security.Cryptography; @@ -367,8 +366,7 @@ private static ExceptionDetail GetDecryptionExceptionDetail( keysAttempted.ToString(), exceptionStrings?.ToString() ?? string.Empty, LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken)), - ExceptionDetail.ExceptionType.SecurityTokenDecryptionFailed, - new StackFrame(true), + ValidationErrorType.SecurityTokenDecryptionFailed, null); else if (algorithmNotSupportedByCryptoProvider) return new ExceptionDetail( @@ -376,16 +374,14 @@ private static ExceptionDetail GetDecryptionExceptionDetail( TokenLogMessages.IDX10619, LogHelper.MarkAsNonPII(decryptionParameters.Alg), LogHelper.MarkAsNonPII(decryptionParameters.Enc)), - ExceptionDetail.ExceptionType.SecurityTokenDecryptionFailed, - new StackFrame(true), + ValidationErrorType.SecurityTokenDecryptionFailed, null); else return new ExceptionDetail( new MessageDetail( TokenLogMessages.IDX10609, LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken)), - ExceptionDetail.ExceptionType.SecurityTokenDecryptionFailed, - new StackFrame(true), + ValidationErrorType.SecurityTokenDecryptionFailed, null); } diff --git a/src/Microsoft.IdentityModel.LoggingExtensions/Microsoft.IdentityModel.LoggingExtensions.csproj b/src/Microsoft.IdentityModel.LoggingExtensions/Microsoft.IdentityModel.LoggingExtensions.csproj index f91d554aec..596fad207c 100644 --- a/src/Microsoft.IdentityModel.LoggingExtensions/Microsoft.IdentityModel.LoggingExtensions.csproj +++ b/src/Microsoft.IdentityModel.LoggingExtensions/Microsoft.IdentityModel.LoggingExtensions.csproj @@ -8,7 +8,7 @@ true Microsoft.IdentityModel.LoggingExtensions .NET;Windows;Authentication;Identity;Extensions;Logging - netstandard2.0 + netstandard2.0;net8.0 enable diff --git a/src/Microsoft.IdentityModel.Tokens/TokenUtilities.cs b/src/Microsoft.IdentityModel.Tokens/TokenUtilities.cs index 00eccab114..c609529e9f 100644 --- a/src/Microsoft.IdentityModel.Tokens/TokenUtilities.cs +++ b/src/Microsoft.IdentityModel.Tokens/TokenUtilities.cs @@ -258,11 +258,11 @@ internal static bool IsRecoverableException(Exception exception) /// /// The exception type to check. /// true if the exception is certain types of exceptions otherwise, false. - internal static bool IsRecoverableExceptionType(ExceptionDetail.ExceptionType exceptionType) + internal static bool IsRecoverableExceptionType(ValidationErrorType exceptionType) { - return exceptionType == ExceptionDetail.ExceptionType.SecurityTokenInvalidSignature - || exceptionType == ExceptionDetail.ExceptionType.SecurityTokenInvalidIssuer - || exceptionType == ExceptionDetail.ExceptionType.SecurityTokenSignatureKeyNotFound; + return exceptionType == ValidationErrorType.SecurityTokenInvalidSignature + || exceptionType == ValidationErrorType.SecurityTokenInvalidIssuer + || exceptionType == ValidationErrorType.SecurityTokenSignatureKeyNotFound; } /// @@ -289,19 +289,19 @@ internal static bool IsRecoverableConfiguration( /// The exception type to check. /// true if the configuration is recoverable otherwise, false. internal static bool IsRecoverableConfigurationAndExceptionType( - string kid, BaseConfiguration currentConfiguration, BaseConfiguration lkgConfiguration, ExceptionDetail.ExceptionType currentExceptionType) + string kid, BaseConfiguration currentConfiguration, BaseConfiguration lkgConfiguration, ValidationErrorType currentExceptionType) { Lazy isRecoverableSigningKey = new(() => lkgConfiguration.SigningKeys.Any(signingKey => signingKey.KeyId == kid)); - if (currentExceptionType == ExceptionDetail.ExceptionType.SecurityTokenInvalidIssuer) + if (currentExceptionType == ValidationErrorType.SecurityTokenInvalidIssuer) { return currentConfiguration.Issuer != lkgConfiguration.Issuer; } - else if (currentExceptionType == ExceptionDetail.ExceptionType.SecurityTokenSignatureKeyNotFound) + else if (currentExceptionType == ValidationErrorType.SecurityTokenSignatureKeyNotFound) { return isRecoverableSigningKey.Value; } - else if (currentExceptionType == ExceptionDetail.ExceptionType.SecurityTokenInvalidSignature) + else if (currentExceptionType == ValidationErrorType.SecurityTokenInvalidSignature) { SecurityKey currentSigningKey = currentConfiguration.SigningKeys.FirstOrDefault(x => x.KeyId == kid); if (currentSigningKey == null) @@ -314,16 +314,16 @@ internal static bool IsRecoverableConfigurationAndExceptionType( return false; } - static ExceptionDetail.ExceptionType ExceptionTypeForException(Exception exception) + static ValidationErrorType ExceptionTypeForException(Exception exception) { if (exception is SecurityTokenInvalidSignatureException) - return ExceptionDetail.ExceptionType.SecurityTokenInvalidSignature; + return ValidationErrorType.SecurityTokenInvalidSignature; else if (exception is SecurityTokenInvalidIssuerException) - return ExceptionDetail.ExceptionType.SecurityTokenInvalidIssuer; + return ValidationErrorType.SecurityTokenInvalidIssuer; else if (exception is SecurityTokenSignatureKeyNotFoundException) - return ExceptionDetail.ExceptionType.SecurityTokenSignatureKeyNotFound; + return ValidationErrorType.SecurityTokenSignatureKeyNotFound; else - return ExceptionDetail.ExceptionType.Unknown; + return ValidationErrorType.Unknown; } } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs index c2416d3be4..c2a442f1d9 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs @@ -18,9 +18,8 @@ internal class ExceptionDetail /// /// contains information about the exception that is used to generate the exception message. /// is the type of exception that occurred. - /// contains information about the stack frame where the exception occurred. - public ExceptionDetail(MessageDetail messageDetail, ExceptionType exceptionType, StackFrame stackFrame) - : this(messageDetail, exceptionType, stackFrame, null) + public ExceptionDetail(MessageDetail messageDetail, ValidationErrorType exceptionType) + : this(messageDetail, exceptionType, null) { } @@ -29,14 +28,12 @@ public ExceptionDetail(MessageDetail messageDetail, ExceptionType exceptionType, /// /// contains information about the exception that is used to generate the exception message. /// is the type of exception that occurred. - /// contains information about the stack frame where the exception occurred. /// is the inner exception that occurred. - public ExceptionDetail(MessageDetail messageDetail, ExceptionType exceptionType, StackFrame stackFrame, Exception innerException) + public ExceptionDetail(MessageDetail messageDetail, ValidationErrorType exceptionType, Exception innerException) { Type = exceptionType; InnerException = innerException; MessageDetail = messageDetail; - StackFrames.Add(stackFrame); } /// @@ -49,13 +46,12 @@ public ExceptionDetail(MessageDetail messageDetail, ExceptionType exceptionType, new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII(parameterName)), - ExceptionType.ArgumentNull, - new StackFrame()); + ValidationErrorType.ArgumentNull); /// /// Gets the type of exception that occurred. /// - public ExceptionType Type { get; } + public ValidationErrorType Type { get; } /// /// Gets the inner exception that occurred. @@ -72,75 +68,49 @@ public ExceptionDetail(MessageDetail messageDetail, ExceptionType exceptionType, /// public IList StackFrames { get; } = []; - public enum ExceptionType - { - Unknown = -1, - ArgumentNull, - InvalidOperation, - SecurityToken, - SecurityTokenDecompressionFailed, - SecurityTokenDecryptionFailed, - SecurityTokenExpired, - SecurityTokenInvalidAudience, - SecurityTokenInvalidAlgorithm, - SecurityTokenInvalidIssuer, - SecurityTokenInvalidLifetime, - SecurityTokenInvalidSigningKey, - SecurityTokenInvalidSignature, - SecurityTokenInvalidType, - SecurityTokenKeyWrap, - SecurityTokenMalformed, - SecurityTokenNoExpiration, - SecurityTokenNotYetValid, - SecurityTokenReplayDetected, - SecurityTokenReplayAddFailed, - SecurityTokenSignatureKeyNotFound, - ExceptionTypeCount - } - - private Exception ExceptionFromType(ExceptionType exceptionType, Exception innerException) + public Exception ExceptionFromType(ValidationErrorType exceptionType, Exception innerException) { switch (exceptionType) { - case ExceptionType.ArgumentNull: + case ValidationErrorType.ArgumentNull: return new ArgumentNullException(MessageDetail.Message, innerException); - case ExceptionType.InvalidOperation: + case ValidationErrorType.InvalidOperation: return new InvalidOperationException(MessageDetail.Message, innerException); - case ExceptionType.SecurityToken: + case ValidationErrorType.SecurityToken: return new SecurityTokenException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenDecompressionFailed: + case ValidationErrorType.SecurityTokenDecompressionFailed: return new SecurityTokenDecompressionFailedException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenDecryptionFailed: + case ValidationErrorType.SecurityTokenDecryptionFailed: return new SecurityTokenDecryptionFailedException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenExpired: + case ValidationErrorType.SecurityTokenExpired: return new SecurityTokenExpiredException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenInvalidAudience: + case ValidationErrorType.SecurityTokenInvalidAudience: return new SecurityTokenInvalidAudienceException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenInvalidAlgorithm: + case ValidationErrorType.SecurityTokenInvalidAlgorithm: return new SecurityTokenInvalidAlgorithmException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenInvalidIssuer: + case ValidationErrorType.SecurityTokenInvalidIssuer: return new SecurityTokenInvalidIssuerException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenInvalidLifetime: + case ValidationErrorType.SecurityTokenInvalidLifetime: return new SecurityTokenInvalidLifetimeException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenInvalidSignature: + case ValidationErrorType.SecurityTokenInvalidSignature: return new SecurityTokenInvalidSignatureException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenInvalidSigningKey: + case ValidationErrorType.SecurityTokenInvalidSigningKey: return new SecurityTokenInvalidSigningKeyException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenInvalidType: + case ValidationErrorType.SecurityTokenInvalidType: return new SecurityTokenInvalidTypeException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenKeyWrap: + case ValidationErrorType.SecurityTokenKeyWrap: return new SecurityTokenKeyWrapException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenMalformed: + case ValidationErrorType.SecurityTokenMalformed: return new SecurityTokenMalformedException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenNoExpiration: + case ValidationErrorType.SecurityTokenNoExpiration: return new SecurityTokenNoExpirationException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenNotYetValid: + case ValidationErrorType.SecurityTokenNotYetValid: return new SecurityTokenNotYetValidException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenReplayDetected: + case ValidationErrorType.SecurityTokenReplayDetected: return new SecurityTokenReplayDetectedException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenReplayAddFailed: + case ValidationErrorType.SecurityTokenReplayAddFailed: return new SecurityTokenReplayAddFailedException(MessageDetail.Message, innerException); - case ExceptionType.SecurityTokenSignatureKeyNotFound: + case ValidationErrorType.SecurityTokenSignatureKeyNotFound: return new SecurityTokenSignatureKeyNotFoundException(MessageDetail.Message, innerException); default: throw new ArgumentException("Invalid ExceptionType."); diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/MessageDetail.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/MessageDetail.cs index 0282247ec3..2ca5dcafb8 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/MessageDetail.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/MessageDetail.cs @@ -8,7 +8,7 @@ namespace Microsoft.IdentityModel.Tokens /// /// Contains information about a message that is used to generate a message for logging or exceptions. /// - internal class MessageDetail + internal struct MessageDetail { private string _message; diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/InternalTokenValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/InternalTokenValidationResult.cs index c4efc371c5..41570c1f65 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/InternalTokenValidationResult.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/InternalTokenValidationResult.cs @@ -16,7 +16,7 @@ internal class InternalTokenValidationResult private bool _isValid; private SecurityToken? _securityToken; private TokenHandler _tokenHandler; - private List _validationResults = []; + private List _validationResults = new List(20); /// /// Creates a new instance of to aggregate validation results. @@ -59,10 +59,9 @@ public bool AddResults(IList validationResults) if (validationResults == null) throw new ArgumentNullException(nameof(validationResults)); - foreach (var validationResult in validationResults) - { - _ = AddResult(validationResult); - } + _validationResults.AddRange(validationResults); + for (int i = 0; i < validationResults.Count; i++) + _isValid = _isValid && validationResults[i].IsValid; return IsValid; } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/SignatureValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/SignatureValidationResult.cs index fc1c2ef3c2..7727a877a3 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/SignatureValidationResult.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/SignatureValidationResult.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Threading; using Microsoft.IdentityModel.Tokens; namespace Microsoft.IdentityModel.JsonWebTokens.Results @@ -14,6 +15,7 @@ namespace Microsoft.IdentityModel.JsonWebTokens.Results internal class SignatureValidationResult : ValidationResult { private Exception? _exception; + private static SignatureValidationResult? _successResult; /// /// Creates an instance of representing the successful result of validating a signature. @@ -38,7 +40,9 @@ public SignatureValidationResult(ValidationFailureType validationFailure, Except /// Creates an instance of representing a successful validation. /// internal static SignatureValidationResult Success() => - new SignatureValidationResult(true, ValidationFailureType.ValidationSucceeded); + _successResult ?? + Interlocked.CompareExchange(ref _successResult, new SignatureValidationResult(true, ValidationFailureType.ValidationSucceeded), null) ?? + _successResult; /// /// Creates an instance of representing a failure due to a null parameter. diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs new file mode 100644 index 0000000000..7c37817080 --- /dev/null +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +namespace Microsoft.IdentityModel.Tokens +{ + internal record struct TokenValidationError( + ValidationErrorType ErrorType, + MessageDetail MessageDetail, + int Tag) + { + } + + internal enum ValidationErrorType + { + Unknown = -1, + ArgumentNull, + InvalidOperation, + SecurityToken, + SecurityTokenDecompressionFailed, + SecurityTokenDecryptionFailed, + SecurityTokenExpired, + SecurityTokenInvalidAudience, + SecurityTokenInvalidAlgorithm, + SecurityTokenInvalidIssuer, + SecurityTokenInvalidLifetime, + SecurityTokenInvalidSigningKey, + SecurityTokenInvalidSignature, + SecurityTokenInvalidType, + SecurityTokenKeyWrap, + SecurityTokenMalformed, + SecurityTokenNoExpiration, + SecurityTokenNotYetValid, + SecurityTokenReplayDetected, + SecurityTokenReplayAddFailed, + SecurityTokenSignatureKeyNotFound, + ExceptionTypeCount + } +} +#nullable restore diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs b/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs index 318f121ecb..fd0be8a668 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs @@ -6,7 +6,7 @@ using System.ComponentModel; using System.Security.Claims; using System.Threading; -using Microsoft.IdentityModel.Abstractions; +//using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; namespace Microsoft.IdentityModel.Tokens @@ -227,8 +227,9 @@ public virtual ClaimsIdentity CreateClaimsIdentity(SecurityToken securityToken, roleClaimType = RoleClaimType; } - if (LogHelper.IsEnabled(EventLogLevel.Informational)) - LogHelper.LogInformation(LogMessages.IDX10245, securityToken); + // TODO: Add to CallContext + //if (LogHelper.IsEnabled(EventLogLevel.Informational)) + // LogHelper.LogInformation(LogMessages.IDX10245, securityToken); return new ClaimsIdentity(authenticationType: AuthenticationType ?? DefaultAuthenticationType, nameType: nameClaimType ?? ClaimsIdentity.DefaultNameClaimType, roleType: roleClaimType ?? ClaimsIdentity.DefaultRoleClaimType); } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs index 684d339c80..f2e024def6 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using System.Diagnostics; using System.Linq; using Microsoft.IdentityModel.Logging; @@ -54,8 +53,7 @@ internal static AlgorithmValidationResult ValidateAlgorithm( new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII(nameof(validationParameters))), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))); + ValidationErrorType.ArgumentNull)); } if (validationParameters.ValidAlgorithms != null && validationParameters.ValidAlgorithms.Count > 0 && !validationParameters.ValidAlgorithms.Contains(algorithm, StringComparer.Ordinal)) @@ -67,8 +65,7 @@ internal static AlgorithmValidationResult ValidateAlgorithm( new MessageDetail( LogMessages.IDX10696, LogHelper.MarkAsNonPII(algorithm)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAlgorithm, - new StackFrame(true))); + ValidationErrorType.SecurityTokenInvalidAlgorithm)); } return new AlgorithmValidationResult(algorithm); diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs index 26ee826da2..717aaa9cd9 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; @@ -54,8 +53,7 @@ internal static AudienceValidationResult ValidateAudience(IList tokenAud new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII(nameof(validationParameters))), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))); + ValidationErrorType.ArgumentNull)); if (tokenAudiences == null) return new AudienceValidationResult( @@ -65,8 +63,7 @@ internal static AudienceValidationResult ValidateAudience(IList tokenAud new MessageDetail( LogMessages.IDX10207, null), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true))); + ValidationErrorType.SecurityTokenInvalidAudience)); if (tokenAudiences.Count == 0) return new AudienceValidationResult( @@ -76,8 +73,7 @@ internal static AudienceValidationResult ValidateAudience(IList tokenAud new MessageDetail( LogMessages.IDX10206, null), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true))); + ValidationErrorType.SecurityTokenInvalidAudience)); string? validAudience = ValidTokenAudience(tokenAudiences, validationParameters.ValidAudiences, validationParameters.IgnoreTrailingSlashWhenValidatingAudience); if (validAudience != null) @@ -91,8 +87,7 @@ internal static AudienceValidationResult ValidateAudience(IList tokenAud LogMessages.IDX10215, LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(tokenAudiences)), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidAudiences))), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true))); + ValidationErrorType.SecurityTokenInvalidAudience)); } private static string? ValidTokenAudience(IList tokenAudiences, IList validAudiences, bool ignoreTrailingSlashWhenValidatingAudience) diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs index 87fca5f32a..8c9cc9a972 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs @@ -1,14 +1,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System.Diagnostics; using System.Threading; using System.Threading.Tasks; -using Microsoft.IdentityModel.Abstractions; +//using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; namespace Microsoft.IdentityModel.Tokens { +#nullable enable /// /// Definition for delegate that will validate the issuer value in a token. /// @@ -45,7 +45,9 @@ internal static async Task ValidateIssuerAsync( string issuer, SecurityToken securityToken, ValidationParameters validationParameters, - CallContext callContext, +#pragma warning disable CA1801 // Review unused parameters + CallContext? callContext, +#pragma warning restore CA1801 // Review unused parameters CancellationToken? cancellationToken) { if (string.IsNullOrWhiteSpace(issuer)) @@ -57,8 +59,7 @@ internal static async Task ValidateIssuerAsync( new MessageDetail( LogMessages.IDX10211, null), - ExceptionDetail.ExceptionType.SecurityTokenInvalidIssuer, - new StackFrame(true), + ValidationErrorType.SecurityTokenInvalidIssuer, null)); } @@ -70,8 +71,7 @@ internal static async Task ValidateIssuerAsync( new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII(nameof(validationParameters))), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true), + ValidationErrorType.ArgumentNull, null)); if (securityToken == null) @@ -82,11 +82,10 @@ internal static async Task ValidateIssuerAsync( new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII(nameof(securityToken))), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true), + ValidationErrorType.ArgumentNull, null)); - BaseConfiguration configuration = null; + BaseConfiguration? configuration = null; if (validationParameters.ConfigurationManager != null) configuration = await validationParameters.ConfigurationManager.GetBaseConfigurationAsync(cancellationToken ?? CancellationToken.None).ConfigureAwait(false); @@ -100,8 +99,7 @@ internal static async Task ValidateIssuerAsync( new MessageDetail( LogMessages.IDX10211, null), - ExceptionDetail.ExceptionType.SecurityTokenInvalidIssuer, - new StackFrame(true))); + ValidationErrorType.SecurityTokenInvalidIssuer)); } if (configuration != null) @@ -111,8 +109,9 @@ internal static async Task ValidateIssuerAsync( // TODO - how and when to log // Logs will have to be passed back to Wilson // so that they can be written to the correct place and in the correct format respecting PII. - if (LogHelper.IsEnabled(EventLogLevel.Informational)) - LogHelper.LogInformation(LogMessages.IDX10236, LogHelper.MarkAsNonPII(issuer), callContext); + // Add to CallContext + //if (LogHelper.IsEnabled(EventLogLevel.Informational)) + // LogHelper.LogInformation(LogMessages.IDX10236, LogHelper.MarkAsNonPII(issuer), callContext); return new IssuerValidationResult(issuer, IssuerValidationResult.ValidationSource.IssuerIsConfigurationIssuer); @@ -125,16 +124,18 @@ internal static async Task ValidateIssuerAsync( { if (string.IsNullOrEmpty(validationParameters.ValidIssuers[i])) { - if (LogHelper.IsEnabled(EventLogLevel.Informational)) - LogHelper.LogInformation(LogMessages.IDX10262); + // TODO: Add to CallContext + //if (LogHelper.IsEnabled(EventLogLevel.Informational)) + // LogHelper.LogInformation(LogMessages.IDX10262); continue; } if (string.Equals(validationParameters.ValidIssuers[i], issuer)) { - if (LogHelper.IsEnabled(EventLogLevel.Informational)) - LogHelper.LogInformation(LogMessages.IDX10236, LogHelper.MarkAsNonPII(issuer)); + // TODO: Add to CallContext + //if (LogHelper.IsEnabled(EventLogLevel.Informational)) + // LogHelper.LogInformation(LogMessages.IDX10236, LogHelper.MarkAsNonPII(issuer)); return new IssuerValidationResult(issuer, IssuerValidationResult.ValidationSource.IssuerIsAmongValidIssuers); @@ -151,8 +152,8 @@ internal static async Task ValidateIssuerAsync( LogHelper.MarkAsNonPII(issuer), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidIssuers)), LogHelper.MarkAsNonPII(configuration?.Issuer)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidIssuer, - new StackFrame(true))); + ValidationErrorType.SecurityTokenInvalidIssuer)); } } +#nullable restore } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs index ea688998e3..4ba55d2fe7 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs @@ -2,9 +2,8 @@ // Licensed under the MIT License. using System; -using System.Diagnostics; using System.Security.Cryptography.X509Certificates; -using Microsoft.IdentityModel.Abstractions; +//using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; #nullable enable @@ -61,8 +60,7 @@ internal static SigningKeyValidationResult ValidateIssuerSigningKey( new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII(nameof(validationParameters))), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))); + ValidationErrorType.ArgumentNull)); if (securityKey == null) { @@ -73,8 +71,7 @@ internal static SigningKeyValidationResult ValidateIssuerSigningKey( new MessageDetail( LogMessages.IDX10253, LogHelper.MarkAsNonPII(nameof(securityKey))), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))); + ValidationErrorType.ArgumentNull)); } if (securityToken == null) @@ -85,8 +82,7 @@ internal static SigningKeyValidationResult ValidateIssuerSigningKey( new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII(nameof(securityToken))), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))); + ValidationErrorType.ArgumentNull)); return ValidateIssuerSigningKeyLifeTime(securityKey, validationParameters, callContext); } @@ -121,11 +117,11 @@ internal static SigningKeyValidationResult ValidateIssuerSigningKeyLifeTime( LogMessages.IDX10248, LogHelper.MarkAsNonPII(notBeforeUtc), LogHelper.MarkAsNonPII(utcNow))), - ExceptionDetail.ExceptionType.SecurityTokenInvalidSigningKey, - new StackFrame(true))); + ValidationErrorType.SecurityTokenInvalidSigningKey)); - if (LogHelper.IsEnabled(EventLogLevel.Informational)) - LogHelper.LogInformation(LogMessages.IDX10250, LogHelper.MarkAsNonPII(notBeforeUtc), LogHelper.MarkAsNonPII(utcNow)); + //TODO: Move to CallContext + //if (LogHelper.IsEnabled(EventLogLevel.Informational)) + // LogHelper.LogInformation(LogMessages.IDX10250, LogHelper.MarkAsNonPII(notBeforeUtc), LogHelper.MarkAsNonPII(utcNow)); if (notAfterUtc < DateTimeUtil.Add(utcNow, validationParameters.ClockSkew.Negate())) return new SigningKeyValidationResult( @@ -137,11 +133,11 @@ internal static SigningKeyValidationResult ValidateIssuerSigningKeyLifeTime( LogMessages.IDX10249, LogHelper.MarkAsNonPII(notAfterUtc), LogHelper.MarkAsNonPII(utcNow))), - ExceptionDetail.ExceptionType.SecurityTokenInvalidSigningKey, - new StackFrame(true))); + ValidationErrorType.SecurityTokenInvalidSigningKey)); - if (LogHelper.IsEnabled(EventLogLevel.Informational)) - LogHelper.LogInformation(LogMessages.IDX10251, LogHelper.MarkAsNonPII(notAfterUtc), LogHelper.MarkAsNonPII(utcNow)); + // TODO: Move to CallContext + //if (LogHelper.IsEnabled(EventLogLevel.Informational)) + // LogHelper.LogInformation(LogMessages.IDX10251, LogHelper.MarkAsNonPII(notAfterUtc), LogHelper.MarkAsNonPII(utcNow)); } return new SigningKeyValidationResult(securityKey); diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs index a56ee6bd9e..00148636a0 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using System.Diagnostics; using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; @@ -60,8 +59,7 @@ internal static LifetimeValidationResult ValidateLifetime(DateTime? notBefore, D new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII(nameof(validationParameters))), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))); + ValidationErrorType.ArgumentNull)); if (!expires.HasValue) return new LifetimeValidationResult( @@ -72,8 +70,7 @@ internal static LifetimeValidationResult ValidateLifetime(DateTime? notBefore, D new MessageDetail( LogMessages.IDX10225, LogHelper.MarkAsNonPII(securityToken == null ? "null" : securityToken.GetType().ToString())), - ExceptionDetail.ExceptionType.SecurityTokenNoExpiration, - new StackFrame(true))); + ValidationErrorType.SecurityTokenNoExpiration)); if (notBefore.HasValue && expires.HasValue && (notBefore.Value > expires.Value)) return new LifetimeValidationResult( @@ -85,8 +82,7 @@ internal static LifetimeValidationResult ValidateLifetime(DateTime? notBefore, D LogMessages.IDX10224, LogHelper.MarkAsNonPII(notBefore.Value), LogHelper.MarkAsNonPII(expires.Value)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidLifetime, - new StackFrame(true))); + ValidationErrorType.SecurityTokenInvalidLifetime)); DateTime utcNow = DateTime.UtcNow; if (notBefore.HasValue && (notBefore.Value > DateTimeUtil.Add(utcNow, validationParameters.ClockSkew))) @@ -99,8 +95,7 @@ internal static LifetimeValidationResult ValidateLifetime(DateTime? notBefore, D LogMessages.IDX10222, LogHelper.MarkAsNonPII(notBefore.Value), LogHelper.MarkAsNonPII(utcNow)), - ExceptionDetail.ExceptionType.SecurityTokenNotYetValid, - new StackFrame(true))); + ValidationErrorType.SecurityTokenNotYetValid)); if (expires.HasValue && (expires.Value < DateTimeUtil.Add(utcNow, validationParameters.ClockSkew.Negate()))) return new LifetimeValidationResult( @@ -112,8 +107,7 @@ internal static LifetimeValidationResult ValidateLifetime(DateTime? notBefore, D LogMessages.IDX10223, LogHelper.MarkAsNonPII(expires.Value), LogHelper.MarkAsNonPII(utcNow)), - ExceptionDetail.ExceptionType.SecurityTokenExpired, - new StackFrame(true))); + ValidationErrorType.SecurityTokenExpired)); // if it reaches here, that means lifetime of the token is valid if (LogHelper.IsEnabled(EventLogLevel.Informational)) diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs index 8d301ea6a8..6f189a8567 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using System.Diagnostics; using Microsoft.IdentityModel.Logging; namespace Microsoft.IdentityModel.Tokens @@ -51,8 +50,7 @@ internal static ReplayValidationResult ValidateTokenReplay(DateTime? expirationT new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII(nameof(securityToken))), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(), + ValidationErrorType.ArgumentNull, null)); if (validationParameters == null) @@ -63,8 +61,7 @@ internal static ReplayValidationResult ValidateTokenReplay(DateTime? expirationT new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII(nameof(validationParameters))), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(), + ValidationErrorType.ArgumentNull, null)); // check if token if replay cache is set, then there must be an expiration time. @@ -78,8 +75,7 @@ internal static ReplayValidationResult ValidateTokenReplay(DateTime? expirationT new MessageDetail( LogMessages.IDX10227, LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), - ExceptionDetail.ExceptionType.SecurityTokenReplayDetected, - new StackFrame(), + ValidationErrorType.SecurityTokenReplayDetected, null)); if (validationParameters.TokenReplayCache.TryFind(securityToken)) @@ -90,8 +86,7 @@ internal static ReplayValidationResult ValidateTokenReplay(DateTime? expirationT new MessageDetail( LogMessages.IDX10228, LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), - ExceptionDetail.ExceptionType.SecurityTokenReplayDetected, - new StackFrame(), + ValidationErrorType.SecurityTokenReplayDetected, null)); if (!validationParameters.TokenReplayCache.TryAdd(securityToken, expirationTime.Value)) @@ -102,13 +97,13 @@ internal static ReplayValidationResult ValidateTokenReplay(DateTime? expirationT new MessageDetail( LogMessages.IDX10229, LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), - ExceptionDetail.ExceptionType.SecurityTokenReplayAddFailed, - new StackFrame(), + ValidationErrorType.SecurityTokenReplayAddFailed, null)); } // if it reaches here, that means no token replay is detected. - LogHelper.LogInformation(LogMessages.IDX10240); + // TODO: Move to CallContext + //LogHelper.LogInformation(LogMessages.IDX10240); return new ReplayValidationResult(expirationTime); } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs index 07af5a4300..855b09a7c8 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs @@ -2,9 +2,8 @@ // Licensed under the MIT License. using System; -using System.Diagnostics; using System.Linq; -using Microsoft.IdentityModel.Abstractions; +//using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; #nullable enable @@ -53,8 +52,7 @@ internal static TokenTypeValidationResult ValidateTokenType( new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII(nameof(securityToken))), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))); + ValidationErrorType.ArgumentNull)); } if (validationParameters == null) @@ -66,8 +64,7 @@ internal static TokenTypeValidationResult ValidateTokenType( new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII(nameof(validationParameters))), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))); + ValidationErrorType.ArgumentNull)); } if (validationParameters.ValidTypes.Count == 0) @@ -85,8 +82,7 @@ internal static TokenTypeValidationResult ValidateTokenType( new MessageDetail( LogMessages.IDX10256, LogHelper.MarkAsNonPII(nameof(type))), - ExceptionDetail.ExceptionType.SecurityTokenInvalidType, - new StackFrame(true))); + ValidationErrorType.SecurityTokenInvalidType)); } if (!validationParameters.ValidTypes.Contains(type, StringComparer.Ordinal)) @@ -99,14 +95,12 @@ internal static TokenTypeValidationResult ValidateTokenType( LogMessages.IDX10257, LogHelper.MarkAsNonPII(nameof(type)), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidTypes))), - ExceptionDetail.ExceptionType.SecurityTokenInvalidType, - new StackFrame(true))); + ValidationErrorType.SecurityTokenInvalidType)); } - if (LogHelper.IsEnabled(EventLogLevel.Informational)) - { - LogHelper.LogInformation(LogMessages.IDX10258, LogHelper.MarkAsNonPII(type)); - } + // TODO: Move to CallContext + //if (LogHelper.IsEnabled(EventLogLevel.Informational)) + // LogHelper.LogInformation(LogMessages.IDX10258, LogHelper.MarkAsNonPII(type)); return new TokenTypeValidationResult(type); } diff --git a/test/Microsoft.IdentityModel.Abstractions.Tests/UnitTests.cs b/test/Microsoft.IdentityModel.Abstractions.Tests/UnitTests.cs new file mode 100644 index 0000000000..eb18a9e259 --- /dev/null +++ b/test/Microsoft.IdentityModel.Abstractions.Tests/UnitTests.cs @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Xunit; + +namespace Microsoft.IdentityModel.Abstractions.Tests +{ + public class UnitTests + { + [Fact] + public void Unit_Default() + { + Assert.Equal(Unit.Default, Unit.Default); + Assert.True(Unit.Default == Unit.Default); + Assert.Equal(Unit.Default, new Unit()); + Assert.True(new Unit() == Unit.Default); + } + } +} diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.DecryptTokenTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.DecryptTokenTests.cs index da65e0afad..097acca16c 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.DecryptTokenTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.DecryptTokenTests.cs @@ -110,7 +110,7 @@ public static TheoryData JsonWebTokenHandlerDecryptTo new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10612), ExceptionDetail.ExceptionType.SecurityToken, - new StackFrame(), null)), + null)), }, new TokenDecryptingTheoryData { @@ -123,8 +123,7 @@ public static TheoryData JsonWebTokenHandlerDecryptTo ValidationFailureType.TokenDecryptionFailed, new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10000, "jwtToken"), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))), + ExceptionDetail.ExceptionType.ArgumentNull)), }, new TokenDecryptingTheoryData { @@ -137,8 +136,7 @@ public static TheoryData JsonWebTokenHandlerDecryptTo ValidationFailureType.TokenDecryptionFailed, new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10000, "validationParameters"), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))), + ExceptionDetail.ExceptionType.ArgumentNull)), }, new TokenDecryptingTheoryData { @@ -205,7 +203,7 @@ public static TheoryData JsonWebTokenHandlerDecryptTo new JsonWebToken(ReferenceTokens.JWEDirectEncryptionUnsignedInnerJWTWithAdditionalHeaderClaims), JwtTokenUtilities.SafeLogJwtToken)), ExceptionDetail.ExceptionType.SecurityTokenDecryptionFailed, - new StackFrame(), null)), + null)), } }; } diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs index 848f414789..3e16ff62dd 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs @@ -71,8 +71,7 @@ public static TheoryData JsonWebTokenHandlerReadTokenTes new MessageDetail( TokenLogMessages.IDX10000, LogHelper.MarkAsNonPII("token")), - ExceptionDetail.ExceptionType.ArgumentNull, - new System.Diagnostics.StackFrame())) + ExceptionDetail.ExceptionType.ArgumentNull)) }, new TokenReadingTheoryData { @@ -86,8 +85,7 @@ public static TheoryData JsonWebTokenHandlerReadTokenTes new MessageDetail( TokenLogMessages.IDX10000, LogHelper.MarkAsNonPII("token")), - ExceptionDetail.ExceptionType.ArgumentNull, - new System.Diagnostics.StackFrame())) + ExceptionDetail.ExceptionType.ArgumentNull)) }, new TokenReadingTheoryData { @@ -103,8 +101,7 @@ public static TheoryData JsonWebTokenHandlerReadTokenTes new MessageDetail( LogMessages.IDX14107, LogHelper.MarkAsNonPII("token")), - ExceptionDetail.ExceptionType.SecurityTokenMalformed, - new System.Diagnostics.StackFrame())) + ExceptionDetail.ExceptionType.SecurityTokenMalformed)) } }; } diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs index e1a3c7c27a..d6a8287810 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs @@ -74,8 +74,7 @@ public static TheoryData JsonWeb new MessageDetail( TokenLogMessages.IDX10000, "jwtToken"), - ExceptionDetail.ExceptionType.ArgumentNull, - new System.Diagnostics.StackFrame())) + ExceptionDetail.ExceptionType.ArgumentNull)) }, new JsonWebTokenHandlerValidateSignatureTheoryData { TestId = "Invalid_Null_ValidationParameters", @@ -88,8 +87,7 @@ public static TheoryData JsonWeb new MessageDetail( TokenLogMessages.IDX10000, "validationParameters"), - ExceptionDetail.ExceptionType.ArgumentNull, - new System.Diagnostics.StackFrame())) + ExceptionDetail.ExceptionType.ArgumentNull)) }, new JsonWebTokenHandlerValidateSignatureTheoryData { TestId = "Invalid_DelegateReturnsFailure", @@ -105,8 +103,7 @@ public static TheoryData JsonWeb new MessageDetail( TokenLogMessages.IDX10000, "fakeParameter"), - ExceptionDetail.ExceptionType.ArgumentNull, - new System.Diagnostics.StackFrame())) + ExceptionDetail.ExceptionType.ArgumentNull)) }, new JsonWebTokenHandlerValidateSignatureTheoryData { @@ -120,8 +117,7 @@ public static TheoryData JsonWeb new MessageDetail( TokenLogMessages.IDX10504, LogHelper.MarkAsSecurityArtifact(unsignedToken, JwtTokenUtilities.SafeLogJwtToken)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidSignature, - new System.Diagnostics.StackFrame())) + ExceptionDetail.ExceptionType.SecurityTokenInvalidSignature)) }, new JsonWebTokenHandlerValidateSignatureTheoryData { @@ -190,8 +186,7 @@ public static TheoryData JsonWeb ValidationFailureType.SignatureValidationFailed, new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10500), - ExceptionDetail.ExceptionType.SecurityTokenSignatureKeyNotFound, - new System.Diagnostics.StackFrame())) + ExceptionDetail.ExceptionType.SecurityTokenSignatureKeyNotFound)) }, new JsonWebTokenHandlerValidateSignatureTheoryData { @@ -203,8 +198,7 @@ public static TheoryData JsonWeb ValidationFailureType.SignatureValidationFailed, new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10500), - ExceptionDetail.ExceptionType.SecurityTokenSignatureKeyNotFound, - new System.Diagnostics.StackFrame())) + ExceptionDetail.ExceptionType.SecurityTokenSignatureKeyNotFound)) } }; } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs index 0dc4f8e77a..3308c7771c 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs @@ -59,8 +59,7 @@ public static TheoryData AlgorithmValidationTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))) + ExceptionDetail.ExceptionType.ArgumentNull)) }, new AlgorithmTheoryData { @@ -81,8 +80,7 @@ public static TheoryData AlgorithmValidationTestCases LogMessages.IDX10696, LogHelper.MarkAsNonPII(SecurityAlgorithms.Sha256), securityKey), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAlgorithm, - new StackFrame(true))) + ExceptionDetail.ExceptionType.SecurityTokenInvalidAlgorithm)) }, new AlgorithmTheoryData { diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs index 064c30be8c..61d31ea072 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using System.Diagnostics; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.TestUtils; @@ -64,7 +63,6 @@ public static TheoryData ValidateAudienceParameter LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true), null)), }, new AudienceValidationTheoryData @@ -80,7 +78,6 @@ public static TheoryData ValidateAudienceParameter LogMessages.IDX10207, null), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), null)), }, new AudienceValidationTheoryData @@ -97,7 +94,7 @@ public static TheoryData ValidateAudienceParameter LogMessages.IDX10206, null), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), + null)), }, new AudienceValidationTheoryData @@ -116,7 +113,7 @@ public static TheoryData ValidateAudienceParameter LogHelper.MarkAsNonPII("audience1"), LogHelper.MarkAsNonPII(String.Empty)), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), + null)), }, new AudienceValidationTheoryData @@ -135,7 +132,7 @@ public static TheoryData ValidateAudienceParameter LogHelper.MarkAsNonPII("audience1"), LogHelper.MarkAsNonPII(" ")), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), + null)), } }; @@ -219,7 +216,7 @@ public static TheoryData ValidateAudienceTheoryDat LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience2)), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), + null)), }, new AudienceValidationTheoryData @@ -239,7 +236,7 @@ public static TheoryData ValidateAudienceTheoryDat LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience2Slash)), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), + null)), }, new AudienceValidationTheoryData @@ -258,7 +255,7 @@ public static TheoryData ValidateAudienceTheoryDat LogHelper.MarkAsNonPII(commaAudience2Slash), LogHelper.MarkAsNonPII(audience1)), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), + null)), }, new AudienceValidationTheoryData @@ -277,7 +274,7 @@ public static TheoryData ValidateAudienceTheoryDat LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience1Slash)), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), + null)), }, new AudienceValidationTheoryData @@ -304,7 +301,7 @@ public static TheoryData ValidateAudienceTheoryDat LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(commaAudience1Slash)), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), + null)), }, new AudienceValidationTheoryData @@ -331,7 +328,7 @@ public static TheoryData ValidateAudienceTheoryDat LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience1 + "A")), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), + null)), }, new AudienceValidationTheoryData @@ -350,7 +347,7 @@ public static TheoryData ValidateAudienceTheoryDat LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience1 + "//")), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), + null)), }, new AudienceValidationTheoryData @@ -369,7 +366,7 @@ public static TheoryData ValidateAudienceTheoryDat LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(commaAudience1 + "//")), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), + null)), }, new AudienceValidationTheoryData @@ -388,7 +385,7 @@ public static TheoryData ValidateAudienceTheoryDat LogHelper.MarkAsNonPII(commaAudience1Slash), LogHelper.MarkAsNonPII(audience1)), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), + null)), }, new AudienceValidationTheoryData @@ -415,7 +412,7 @@ public static TheoryData ValidateAudienceTheoryDat LogHelper.MarkAsNonPII(commaAudience2Slash), LogHelper.MarkAsNonPII(audience1)), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), + null)), }, new AudienceValidationTheoryData @@ -434,7 +431,7 @@ public static TheoryData ValidateAudienceTheoryDat LogHelper.MarkAsNonPII(commaAudience1Slash), LogHelper.MarkAsNonPII(audience1)), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), + null)), }, new AudienceValidationTheoryData @@ -461,7 +458,6 @@ public static TheoryData ValidateAudienceTheoryDat LogHelper.MarkAsNonPII(commaAudience1Slash), LogHelper.MarkAsNonPII(commaAudience2)), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), null)), }, new AudienceValidationTheoryData @@ -480,7 +476,7 @@ public static TheoryData ValidateAudienceTheoryDat LogHelper.MarkAsNonPII(commaAudience1 + "//"), LogHelper.MarkAsNonPII(audience1)), ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - new StackFrame(true), + null)), } }; diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ExceptionDetailsTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ExceptionDetailsTests.cs index 62b1bd2418..a0fa29f323 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ExceptionDetailsTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ExceptionDetailsTests.cs @@ -17,8 +17,7 @@ public void ExceptionDetails(ExceptionDetailsTheoryData theoryData) var context = TestUtilities.WriteHeader($"{this}.ExceptionDetails", theoryData); ExceptionDetail exceptionDetail = new ExceptionDetail( new MessageDetail(""), - theoryData.ExceptionType, - new System.Diagnostics.StackFrame()); + theoryData.ExceptionType); theoryData.ExpectedException.ProcessException(exceptionDetail.GetException(), context); @@ -30,8 +29,7 @@ public void ExceptionDetails_UnknownType_Throws() { ExceptionDetail exceptionDetail = new ExceptionDetail( new MessageDetail(""), - ExceptionDetail.ExceptionType.Unknown, - new System.Diagnostics.StackFrame()); + ExceptionDetail.ExceptionType.Unknown); Assert.Throws(() => exceptionDetail.GetException()); } @@ -176,6 +174,6 @@ public static TheoryData ExceptionDetailsTestCases public class ExceptionDetailsTheoryData : TheoryDataBase { - internal ExceptionDetail.ExceptionType ExceptionType { get; set; } + internal ValidationErrorType ExceptionType { get; set; } } } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs index 2a887b10d3..ad31043587 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs @@ -68,8 +68,7 @@ public static TheoryData IssuerValdationResul LogHelper.MarkAsNonPII(validIssuer), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(null)), LogHelper.MarkAsNonPII(null)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidIssuer, - new StackFrame(true))), + ExceptionDetail.ExceptionType.SecurityTokenInvalidIssuer)), IsValid = false, SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, issClaim), ValidationParameters = new ValidationParameters() @@ -87,7 +86,6 @@ public static TheoryData IssuerValdationResul LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true), null)), IsValid = false, SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, issClaim), @@ -106,7 +104,6 @@ public static TheoryData IssuerValdationResul LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true), null)), IsValid = false, SecurityToken = null, @@ -154,8 +151,7 @@ public static TheoryData IssuerValdationResul LogHelper.MarkAsNonPII(issClaim), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validIssuers)), LogHelper.MarkAsNonPII(null)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidIssuer, - new StackFrame(true))), + ExceptionDetail.ExceptionType.SecurityTokenInvalidIssuer)), IsValid = false, SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, issClaim), ValidationParameters = new ValidationParameters(), diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs index 03eb7a9f6b..f8b6a4efc3 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs @@ -96,7 +96,6 @@ public static TheoryData ValidateLifetimeTestCases LogMessages.IDX10000, "validationParameters"), ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true), null)), }, new ValidateLifetimeTheoryData("Invalid_ExpiresIsNull") @@ -113,7 +112,6 @@ public static TheoryData ValidateLifetimeTestCases LogMessages.IDX10225, "null"), ExceptionDetail.ExceptionType.SecurityTokenNoExpiration, - new StackFrame(true), null)), }, new ValidateLifetimeTheoryData("Invalid_NotBeforeIsAfterExpires") @@ -132,7 +130,6 @@ public static TheoryData ValidateLifetimeTestCases LogHelper.MarkAsNonPII(oneHourFromNow), LogHelper.MarkAsNonPII(oneHourAgo)), ExceptionDetail.ExceptionType.SecurityTokenInvalidLifetime, - new StackFrame(true), null)), }, new ValidateLifetimeTheoryData("Invalid_NotYetValid") @@ -151,7 +148,6 @@ public static TheoryData ValidateLifetimeTestCases LogHelper.MarkAsNonPII(oneHourFromNow), LogHelper.MarkAsNonPII(now)), ExceptionDetail.ExceptionType.SecurityTokenNotYetValid, - new StackFrame(true), null)), }, new ValidateLifetimeTheoryData("Invalid_Expired") @@ -170,7 +166,6 @@ public static TheoryData ValidateLifetimeTestCases LogHelper.MarkAsNonPII(oneHourAgo), LogHelper.MarkAsNonPII(now)), ExceptionDetail.ExceptionType.SecurityTokenExpired, - new StackFrame(true), null)), }, new ValidateLifetimeTheoryData("Invalid_NotYetValid_SkewForward") @@ -189,7 +184,6 @@ public static TheoryData ValidateLifetimeTestCases LogHelper.MarkAsNonPII(sixMinutesFromNow), LogHelper.MarkAsNonPII(now)), ExceptionDetail.ExceptionType.SecurityTokenNotYetValid, - new StackFrame(true), null)), }, new ValidateLifetimeTheoryData("Invalid_Expired_SkewBackward") @@ -208,7 +202,6 @@ public static TheoryData ValidateLifetimeTestCases LogHelper.MarkAsNonPII(sixMinutesAgo), LogHelper.MarkAsNonPII(now)), ExceptionDetail.ExceptionType.SecurityTokenExpired, - new StackFrame(true), null)), } }; diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs index 5d6124452f..9ff01eed65 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs @@ -83,7 +83,6 @@ public static TheoryData TokenReplayValidationTestCases LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(), null)) }, new TokenReplayTheoryData @@ -101,7 +100,6 @@ public static TheoryData TokenReplayValidationTestCases LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(), null)) }, new TokenReplayTheoryData @@ -119,7 +117,6 @@ public static TheoryData TokenReplayValidationTestCases LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(), null)) }, new TokenReplayTheoryData @@ -144,7 +141,6 @@ public static TheoryData TokenReplayValidationTestCases LogMessages.IDX10227, LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), ExceptionDetail.ExceptionType.SecurityTokenReplayDetected, - new StackFrame(), null)) }, new TokenReplayTheoryData @@ -169,7 +165,6 @@ public static TheoryData TokenReplayValidationTestCases LogMessages.IDX10228, LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), ExceptionDetail.ExceptionType.SecurityTokenReplayDetected, - new StackFrame(), null)) }, new TokenReplayTheoryData @@ -194,7 +189,6 @@ public static TheoryData TokenReplayValidationTestCases LogMessages.IDX10229, LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), ExceptionDetail.ExceptionType.SecurityTokenReplayDetected, - new StackFrame(), null)) } }; diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs index 1a2f055d3d..c6c38d3474 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs @@ -68,8 +68,7 @@ public static TheoryData SigningKeyValidationTes ValidationFailureType.NullArgument, new ExceptionDetail( new MessageDetail(LogMessages.IDX10253), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))) + ExceptionDetail.ExceptionType.ArgumentNull)) }, new SigningKeyValidationTheoryData { @@ -85,8 +84,7 @@ public static TheoryData SigningKeyValidationTes new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))) + ExceptionDetail.ExceptionType.ArgumentNull)) }, new SigningKeyValidationTheoryData { @@ -102,8 +100,7 @@ public static TheoryData SigningKeyValidationTes new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))) + ExceptionDetail.ExceptionType.ArgumentNull)) }, new SigningKeyValidationTheoryData { @@ -120,8 +117,7 @@ public static TheoryData SigningKeyValidationTes LogMessages.IDX10249, LogHelper.MarkAsNonPII(utcExpired), LogHelper.MarkAsNonPII(utcNow)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidSigningKey, - new StackFrame(true))) + ExceptionDetail.ExceptionType.SecurityTokenInvalidSigningKey)) }, new SigningKeyValidationTheoryData { @@ -138,8 +134,7 @@ public static TheoryData SigningKeyValidationTes LogMessages.IDX10248, LogHelper.MarkAsNonPII(utcNotYetValid), LogHelper.MarkAsNonPII(utcNow)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidSigningKey, - new StackFrame(true))) + ExceptionDetail.ExceptionType.SecurityTokenInvalidSigningKey)) }, new SigningKeyValidationTheoryData { @@ -153,8 +148,7 @@ public static TheoryData SigningKeyValidationTes ValidationFailureType.NullArgument, new ExceptionDetail( new MessageDetail(LogMessages.IDX10253), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))) + ExceptionDetail.ExceptionType.ArgumentNull)) }, }; diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs index 11548f61ad..c505875577 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using System.Diagnostics; using Microsoft.IdentityModel.TestUtils; using Microsoft.IdentityModel.Tokens.Json.Tests; using Microsoft.IdentityModel.JsonWebTokens; @@ -77,8 +76,7 @@ public static TheoryData TokenTypeValidationTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))) + ExceptionDetail.ExceptionType.ArgumentNull)) }, new TokenTypeTheoryData { @@ -94,8 +92,7 @@ public static TheoryData TokenTypeValidationTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), - ExceptionDetail.ExceptionType.ArgumentNull, - new StackFrame(true))) + ExceptionDetail.ExceptionType.ArgumentNull)) }, new TokenTypeTheoryData { @@ -112,8 +109,7 @@ public static TheoryData TokenTypeValidationTestCases new MessageDetail( LogMessages.IDX10256, LogHelper.MarkAsNonPII("type")), - ExceptionDetail.ExceptionType.SecurityTokenInvalidType, - new StackFrame(true))) + ExceptionDetail.ExceptionType.SecurityTokenInvalidType)) }, new TokenTypeTheoryData { @@ -130,8 +126,7 @@ public static TheoryData TokenTypeValidationTestCases new MessageDetail( LogMessages.IDX10256, LogHelper.MarkAsNonPII("type")), - ExceptionDetail.ExceptionType.SecurityTokenInvalidType, - new StackFrame(true))) + ExceptionDetail.ExceptionType.SecurityTokenInvalidType)) }, new TokenTypeTheoryData { @@ -149,8 +144,7 @@ public static TheoryData TokenTypeValidationTestCases LogMessages.IDX10257, LogHelper.MarkAsNonPII("type"), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validTypesNoJwt))), - ExceptionDetail.ExceptionType.SecurityTokenInvalidType, - new StackFrame(true))) + ExceptionDetail.ExceptionType.SecurityTokenInvalidType)) } }; } From a61ca89edad22be1e9350bc6acb2d51df77372ef Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Tue, 20 Aug 2024 17:31:03 +0100 Subject: [PATCH 06/32] Work in progress --- ...TokenAsyncWithValidationParametersTests.cs | 114 ++++---- .../Result.cs | 4 - .../JsonWebTokenHandler.DecryptToken.cs | 58 ++-- .../JsonWebTokenHandler.ReadToken.cs | 20 +- .../JsonWebTokenHandler.ValidateSignature.cs | 192 ++++++------- ...nWebTokenHandler.ValidateToken.Internal.cs | 252 ++++++++++++------ .../JwtTokenUtilities.DecryptTokenResult.cs | 59 ++-- .../JwtTokenUtilities.cs | 25 +- .../Delegates.cs | 4 +- .../LogMessages.cs | 1 + .../TokenUtilities.cs | 18 +- .../Results/AlgorithmValidationResult.cs | 70 ----- .../Results/AudienceValidationResult.cs | 67 ----- .../Results/Details/ExceptionDetail.cs | 54 ++-- .../Results/Details/MessageDetail.cs | 5 +- .../Results/InternalTokenValidationResult.cs | 145 ---------- .../Results/IssuerValidationResult.cs | 83 ------ .../Results/LifetimeValidationResult.cs | 78 ------ .../Results/ReplayValidationResult.cs | 73 ----- .../Results/SignatureValidationResult.cs | 80 ------ .../Results/SigningKeyValidationResult.cs | 69 ----- .../Results/TokenDecryptionResult.cs | 97 ------- .../Validation/Results/TokenReadingResult.cs | 86 ------ .../Results/TokenTypeValidationResult.cs | 70 ----- .../Results/TokenValidationError.cs | 30 ++- .../Results/TokenValidationResult.cs | 71 ++--- .../Validation/Results/ValidationResult.cs | 113 +++----- .../Validation/ValidationParameters.cs | 4 +- .../Validation/Validators.Algorithm.cs | 37 +-- .../Validation/Validators.Audience.cs | 58 ++-- .../Validation/Validators.Issuer.cs | 97 +++---- .../Validation/Validators.IssuerSigningKey.cs | 94 +++---- .../Validation/Validators.Lifetime.cs | 98 +++---- .../Validation/Validators.TokenReplay.cs | 77 ++---- .../Validation/Validators.TokenType.cs | 69 ++--- 35 files changed, 746 insertions(+), 1726 deletions(-) delete mode 100644 src/Microsoft.IdentityModel.Tokens/Validation/Results/AlgorithmValidationResult.cs delete mode 100644 src/Microsoft.IdentityModel.Tokens/Validation/Results/AudienceValidationResult.cs delete mode 100644 src/Microsoft.IdentityModel.Tokens/Validation/Results/InternalTokenValidationResult.cs delete mode 100644 src/Microsoft.IdentityModel.Tokens/Validation/Results/IssuerValidationResult.cs delete mode 100644 src/Microsoft.IdentityModel.Tokens/Validation/Results/LifetimeValidationResult.cs delete mode 100644 src/Microsoft.IdentityModel.Tokens/Validation/Results/ReplayValidationResult.cs delete mode 100644 src/Microsoft.IdentityModel.Tokens/Validation/Results/SignatureValidationResult.cs delete mode 100644 src/Microsoft.IdentityModel.Tokens/Validation/Results/SigningKeyValidationResult.cs delete mode 100644 src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenDecryptionResult.cs delete mode 100644 src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenReadingResult.cs delete mode 100644 src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenTypeValidationResult.cs diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs index 2b916594d1..7cbe45111c 100644 --- a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs +++ b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs @@ -1,14 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; using System.Threading.Tasks; using BenchmarkDotNet.Attributes; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; -using System; namespace Microsoft.IdentityModel.Benchmarks { @@ -81,92 +77,96 @@ public void Setup() } [Benchmark] - public async Task JsonWebTokenHandler_01_ValidateTokenAsyncWithTVP() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); + public async Task JsonWebTokenHandler_01_ValidateTokenAsyncWithTVP() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false) != null; [Benchmark] - public async Task JsonWebTokenHandler_02_ValidateTokenAsyncWithTVPUsingClone() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false); + public async Task JsonWebTokenHandler_02_ValidateTokenAsyncWithTVPUsingClone() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false) != null; [Benchmark] - public async Task JsonWebTokenHandler_03_ValidateTokenAsyncWithVP() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + public async Task JsonWebTokenHandler_03_ValidateTokenAsyncWithVP() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false) != null; [Benchmark] - public async Task JsonWebTokenHandler_04_ValidateTokenAsyncWithTVP_SucceedOnThirdAttempt() + public async Task JsonWebTokenHandler_04_ValidateTokenAsyncWithTVP_SucceedOnThirdAttempt() { - TokenValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); - return result; + return true; } [Benchmark] - public async Task JsonWebTokenHandler_05_ValidateTokenAsyncWithTVPUsingClone_SucceedOnThirdAttempt() + public async Task JsonWebTokenHandler_05_ValidateTokenAsyncWithTVPUsingClone_SucceedOnThirdAttempt() { - TokenValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false); - return result; + return true; } [Benchmark] - public async Task JsonWebTokenHandler_06_ValidateTokenAsyncWithVP_SucceedOnThirdAttempt() + public async Task JsonWebTokenHandler_06_ValidateTokenAsyncWithVP_SucceedOnThirdAttempt() { - var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - return await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + + return true; } [Benchmark] - public async Task JsonWebTokenHandler_07_ValidateTokenAsyncWithTVP_SucceedOnFifthAttempt() + public async Task JsonWebTokenHandler_07_ValidateTokenAsyncWithTVP_SucceedOnFifthAttempt() { - TokenValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); - return result; + return true; } [Benchmark] - public async Task JsonWebTokenHandler_08_ValidateTokenAsyncWithTVPUsingClone_SucceedOnFifthAttempt() + public async Task JsonWebTokenHandler_08_ValidateTokenAsyncWithTVPUsingClone_SucceedOnFifthAttempt() { - TokenValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false); - return result; + return true; } [Benchmark] - public async Task JsonWebTokenHandler_09_ValidateTokenAsyncWithVP_SucceedOnFifthAttempt() + public async Task JsonWebTokenHandler_09_ValidateTokenAsyncWithVP_SucceedOnFifthAttempt() { - var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - return await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); - } + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); - [Benchmark] - public async Task> JsonWebTokenHandler_10_ValidateTokenAsyncWithTVP_CreateClaims() - { - var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false); - var claimsIdentity = result.ClaimsIdentity; - var claims = claimsIdentity.Claims; - return claims.ToList(); + return true; } - [Benchmark] - public async Task> JsonWebTokenHandler_11_ValidateTokenAsyncWithVP_CreateClaims() - { - var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); - var claimsIdentity = result.ClaimsIdentity; - var claims = claimsIdentity.Claims; - return claims.ToList(); - } + //[Benchmark] + //public async Task> JsonWebTokenHandler_10_ValidateTokenAsyncWithTVP_CreateClaims() + //{ + // var await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false); + // var claimsIdentity = result.ClaimsIdentity; + // var claims = claimsIdentity.Claims; + // return claims.ToList(); + //} + + //[Benchmark] + //public async Task> JsonWebTokenHandler_11_ValidateTokenAsyncWithVP_CreateClaims() + //{ + // var await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + // var claimsIdentity = result.ClaimsIdentity; + // var claims = claimsIdentity.Claims; + // return claims.ToList(); + //} } } diff --git a/src/Microsoft.IdentityModel.Abstractions/Result.cs b/src/Microsoft.IdentityModel.Abstractions/Result.cs index c45f0b80e7..11062f8e96 100644 --- a/src/Microsoft.IdentityModel.Abstractions/Result.cs +++ b/src/Microsoft.IdentityModel.Abstractions/Result.cs @@ -82,13 +82,9 @@ public override bool Equals(object? obj) public override int GetHashCode() { if (IsSuccess) - { return _result!.GetHashCode(); - } else - { return _error!.GetHashCode(); - } } /// diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs index 3bc83fdd96..e7e4df70e7 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -//using Microsoft.IdentityModel.Abstractions; +using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Tokens; using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages; @@ -23,49 +23,38 @@ public partial class JsonWebTokenHandler : TokenHandler /// The to be used for validating the token. /// /// The decoded / cleartext contents of the JWE. - /// Returned inside if is null. - /// Returned inside if is null. - /// Returned inside if is null or empty. - /// Returned inside if the decompression failed. - /// Returned inside if is not null AND the decryption fails. - /// Returned inside if the JWE was not able to be decrypted. - internal TokenDecryptionResult DecryptToken( + internal Result DecryptToken( JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration configuration, CallContext? callContext) { if (jwtToken == null) - return TokenDecryptionResult.NullParameterFailure(jwtToken, nameof(jwtToken)); + return new(TokenValidationErrorCommon.NullParameter(nameof(jwtToken), 0x123123)); if (validationParameters == null) - return TokenDecryptionResult.NullParameterFailure(jwtToken, nameof(validationParameters)); + return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123124)); if (string.IsNullOrEmpty(jwtToken.Enc)) - return new TokenDecryptionResult( - jwtToken, - ValidationFailureType.TokenDecryptionFailed, - new ExceptionDetail( - new MessageDetail(TokenLogMessages.IDX10612), - ValidationErrorType.SecurityToken)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenDecryptionFailed, + new MessageDetail(TokenLogMessages.IDX10612), + Tag: 0x123125, + null)); var keysOrExceptionDetail = GetContentEncryptionKeys(jwtToken, validationParameters, configuration, callContext); - if (keysOrExceptionDetail.Item2 != null) // ExceptionDetail returned - return new TokenDecryptionResult( - jwtToken, - ValidationFailureType.TokenDecryptionFailed, - keysOrExceptionDetail.Item2); + if (keysOrExceptionDetail.Item2 != null) // TokenValidationError returned + return new(keysOrExceptionDetail.Item2); var keys = keysOrExceptionDetail.Item1; if (keys == null) - return new TokenDecryptionResult( - jwtToken, - ValidationFailureType.TokenDecryptionFailed, - new ExceptionDetail( - new MessageDetail( - TokenLogMessages.IDX10609, - LogHelper.MarkAsSecurityArtifact(jwtToken, JwtTokenUtilities.SafeLogJwtToken)), - ValidationErrorType.SecurityTokenDecryptionFailed)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenKeyWrap, + new MessageDetail( + TokenLogMessages.IDX10609, + LogHelper.MarkAsSecurityArtifact(jwtToken, JwtTokenUtilities.SafeLogJwtToken)), + Tag: 0x123126, + null)); return JwtTokenUtilities.DecryptJwtToken( jwtToken, @@ -79,7 +68,7 @@ internal TokenDecryptionResult DecryptToken( callContext); } - internal (IList?, ExceptionDetail?) GetContentEncryptionKeys(JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration configuration, CallContext? callContext) + internal (IList?, TokenValidationError?) GetContentEncryptionKeys(JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration configuration, CallContext? callContext) { IList? keys = null; @@ -196,14 +185,17 @@ internal TokenDecryptionResult DecryptToken( return (unwrappedKeys, null); else { - ExceptionDetail exceptionDetail = new( + TokenValidationError tokenValidationError = new( + ValidationErrorType.SecurityTokenKeyWrap, new MessageDetail( TokenLogMessages.IDX10618, keysAttempted?.ToString() ?? "", exceptionStrings?.ToString() ?? "", LogHelper.MarkAsSecurityArtifact(jwtToken, JwtTokenUtilities.SafeLogJwtToken)), - ValidationErrorType.SecurityTokenKeyWrap); - return (null, exceptionDetail); + Tag: 0x123126, + null); + + return (null, tokenValidationError); } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs index 8b389f486c..e4c242738c 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs @@ -3,9 +3,7 @@ using System; using Microsoft.IdentityModel.Abstractions; -using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Tokens; -using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages; namespace Microsoft.IdentityModel.JsonWebTokens { @@ -14,29 +12,22 @@ public partial class JsonWebTokenHandler : TokenHandler { #nullable enable /// - /// Converts a string into an instance of , returned inside of a . + /// Converts a string into an instance of , returned inside of a . /// /// A JSON Web Token (JWT) in JWS or JWE Compact Serialization format. /// - /// A with the if valid, or an Exception. + /// A with the if valid, or an error. /// returned if is null or empty. /// returned if the validationParameters.TokenReader delegate is not able to parse/read the token as a valid . /// returned if is not a valid JWT, . - internal static Result ReadToken( + internal static Result ReadToken( string token, #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging CallContext? callContext) #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging { if (String.IsNullOrEmpty(token)) - { - return new(new TokenValidationError( - ValidationErrorType.Unknown, - new MessageDetail( - TokenLogMessages.IDX10000, - LogHelper.MarkAsNonPII(nameof(token))), - 0x123123)); - } + return new(TokenValidationErrorCommon.NullParameter(nameof(token), 0x123123)); try { @@ -50,7 +41,8 @@ internal static Result ReadToken( return new(new TokenValidationError( ValidationErrorType.SecurityTokenMalformed, new MessageDetail(LogMessages.IDX14107), - Tag: 0x123456)); + Tag: 0x123456, + null)); } } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs index 4ad91e92d1..f3ca3268e0 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using Microsoft.IdentityModel.JsonWebTokens.Results; +using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Tokens; using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages; @@ -27,17 +27,17 @@ public partial class JsonWebTokenHandler : TokenHandler /// Returned by the default implementation if the token is not signed, or if the validation fails. /// Returned if the algorithm is not supported by the key. /// Returned if the key cannot be resolved. - internal static SignatureValidationResult ValidateSignature( + internal static Result ValidateSignature( JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration? configuration, CallContext callContext) { if (jwtToken is null) - return SignatureValidationResult.NullParameterFailure(nameof(jwtToken)); + return new(TokenValidationErrorCommon.NullParameter(nameof(jwtToken), 0x123123)); if (validationParameters is null) - return SignatureValidationResult.NullParameterFailure(nameof(validationParameters)); + return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123123)); // Delegate is set by the user, we call it and return the result. if (validationParameters.SignatureValidator is not null) @@ -45,16 +45,15 @@ internal static SignatureValidationResult ValidateSignature( // If the user wants to accept unsigned tokens, they must implement the delegate. if (!jwtToken.IsSigned) - return new SignatureValidationResult( - ValidationFailureType.SignatureValidationFailed, - new ExceptionDetail( - new MessageDetail( - TokenLogMessages.IDX10504, - LogHelper.MarkAsSecurityArtifact( - jwtToken.EncodedToken, - JwtTokenUtilities.SafeLogJwtToken) - ), - ValidationErrorType.SecurityTokenInvalidSignature)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidSignature, + new MessageDetail( + TokenLogMessages.IDX10504, + LogHelper.MarkAsSecurityArtifact( + jwtToken.EncodedToken, + JwtTokenUtilities.SafeLogJwtToken)), + 0x123123, + null)); SecurityKey? key = null; if (validationParameters.IssuerSigningKeyResolver is not null) @@ -87,14 +86,14 @@ internal static SignatureValidationResult ValidateSignature( if (validationParameters.TryAllIssuerSigningKeys) return ValidateSignatureUsingAllKeys(jwtToken, validationParameters, configuration, callContext); else - return new SignatureValidationResult( - ValidationFailureType.SignatureValidationFailed, - new ExceptionDetail( - new MessageDetail(TokenLogMessages.IDX10500), - ValidationErrorType.SecurityTokenSignatureKeyNotFound)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenSignatureKeyNotFound, + new MessageDetail(TokenLogMessages.IDX10500), + 0x123123, + null)); } - private static SignatureValidationResult ValidateSignatureUsingAllKeys( + private static Result ValidateSignatureUsingAllKeys( JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration? configuration, @@ -104,30 +103,30 @@ private static SignatureValidationResult ValidateSignatureUsingAllKeys( // 1. User specified delegate: IssuerSigningKeyResolver returned null // 2. ResolveIssuerSigningKey returned null // Try all the keys. This is the degenerate case, not concerned about perf. - (SignatureValidationResult? configResult, bool configKidMatched, KeyMatchFailedResult? configFailedResult) = ValidateUsingKeys( + (Result? configResult, bool configKidMatched, KeyMatchFailedResult? configFailedResult) = ValidateUsingKeys( jwtToken, validationParameters, configuration?.SigningKeys, callContext); - if (configResult is not null) - return configResult; + if (configResult is Result unwrappedConfigResult) + return unwrappedConfigResult; - (SignatureValidationResult? vpResult, bool vpKidMatched, KeyMatchFailedResult? vpFailedResult) = ValidateUsingKeys( + (Result? vpResult, bool vpKidMatched, KeyMatchFailedResult? vpFailedResult) = ValidateUsingKeys( jwtToken, validationParameters, validationParameters.IssuerSigningKeys, callContext); - if (vpResult is not null) - return vpResult; + if (vpResult is Result unwrappedVpResult) + return unwrappedVpResult; if (vpFailedResult is null && configFailedResult is null) // No keys were attempted - return new SignatureValidationResult( - ValidationFailureType.SignatureValidationFailed, - new ExceptionDetail( - new MessageDetail(TokenLogMessages.IDX10500), - ValidationErrorType.SecurityTokenSignatureKeyNotFound)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenSignatureKeyNotFound, + new MessageDetail(TokenLogMessages.IDX10500), + 0x123123, + null)); StringBuilder exceptionStrings = new(); StringBuilder keysAttempted = new(); @@ -139,19 +138,17 @@ private static SignatureValidationResult ValidateSignatureUsingAllKeys( bool kidMatched = configKidMatched || vpKidMatched; // No valid signature found. Return the exception details. - return new SignatureValidationResult( - ValidationFailureType.SignatureValidationFailed, - GetSignatureValidationFailureExceptionDetails( - jwtToken, - validationParameters, - configuration, - exceptionStrings, - keysAttempted, - kidExists, - kidMatched)); + return new(GetSignatureValidationError( + jwtToken, + validationParameters, + configuration, + exceptionStrings, + keysAttempted, + kidExists, + kidMatched)); } - private static (SignatureValidationResult? validResult, bool KidMatched, KeyMatchFailedResult? failedResult) ValidateUsingKeys( + private static (Result? validResult, bool KidMatched, KeyMatchFailedResult? failedResult) ValidateUsingKeys( JsonWebToken jwtToken, ValidationParameters validationParameters, ICollection? keys, @@ -166,36 +163,36 @@ private static (SignatureValidationResult? validResult, bool KidMatched, KeyMatc bool kidExists = !string.IsNullOrEmpty(jwtToken.Kid); bool kidMatched = false; IList? keysAttempted = null; - IList? results = null; + IList? errors = null; for (int i = 0; i < keysList.Count; i++) { SecurityKey key = keysList[i]; - SignatureValidationResult result = ValidateSignatureWithKey(jwtToken, key, validationParameters, callContext); - if (result.IsValid) + Result result = ValidateSignatureWithKey(jwtToken, key, validationParameters, callContext); + if (result.IsSuccess) { jwtToken.SigningKey = key; return (result, true, null); } keysAttempted ??= []; - results ??= []; + errors ??= []; - results.Add(result); + errors.Add(result.UnwrapError()); keysAttempted.Add(key); if (kidExists && !kidMatched && key.KeyId is not null) kidMatched = jwtToken.Kid.Equals(key.KeyId, key is X509SecurityKey ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal); } - if (results is not null && results.Count > 0 && keysAttempted is not null && keysAttempted.Count > 0) - return (null, kidMatched, new KeyMatchFailedResult(results, keysAttempted)); + if (errors is not null && errors.Count > 0 && keysAttempted is not null && keysAttempted.Count > 0) + return (null, kidMatched, new KeyMatchFailedResult(errors, keysAttempted)); // No keys were attempted. return (null, kidMatched, null); } - private static SignatureValidationResult ValidateSignatureWithKey( + private static Result ValidateSignatureWithKey( JsonWebToken jsonWebToken, SecurityKey key, ValidationParameters validationParameters, @@ -204,38 +201,38 @@ private static SignatureValidationResult ValidateSignatureWithKey( CryptoProviderFactory cryptoProviderFactory = validationParameters.CryptoProviderFactory ?? key.CryptoProviderFactory; if (!cryptoProviderFactory.IsSupportedAlgorithm(jsonWebToken.Alg, key)) { - return new SignatureValidationResult( - ValidationFailureType.SignatureValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX14000, - LogHelper.MarkAsNonPII(jsonWebToken.Alg), - key), - ValidationErrorType.SecurityTokenInvalidAlgorithm)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAlgorithm, + new MessageDetail( + LogMessages.IDX14000, + LogHelper.MarkAsNonPII(jsonWebToken.Alg), + key), + 0x123123, + null)); } - AlgorithmValidationResult result = validationParameters.AlgorithmValidator( + Result result = validationParameters.AlgorithmValidator( jsonWebToken.Alg, key, jsonWebToken, validationParameters, callContext); - if (!result.IsValid) - return new SignatureValidationResult( - ValidationFailureType.SignatureValidationFailed, - result.ExceptionDetail); + + if (!result.IsSuccess) + return new(result.UnwrapError()); SignatureProvider signatureProvider = cryptoProviderFactory.CreateForVerifying(key, jsonWebToken.Alg); try { if (signatureProvider == null) - return new SignatureValidationResult( - ValidationFailureType.SignatureValidationFailed, - new ExceptionDetail( - new MessageDetail(TokenLogMessages.IDX10636, - key?.ToString() ?? "Null", - LogHelper.MarkAsNonPII(jsonWebToken.Alg)), - ValidationErrorType.InvalidOperation)); + return new(new TokenValidationError( + ValidationErrorType.InvalidOperation, + new MessageDetail( + TokenLogMessages.IDX10636, + key?.ToString() ?? "Null", + LogHelper.MarkAsNonPII(jsonWebToken.Alg)), + 0x123123, + null)); bool valid = EncodingUtils.PerformEncodingDependentOperation( jsonWebToken.EncodedToken, @@ -248,23 +245,30 @@ private static SignatureValidationResult ValidateSignatureWithKey( ValidateSignature); if (valid) - return SignatureValidationResult.Success(); + return new(key); else - return new SignatureValidationResult( - ValidationFailureType.SignatureValidationFailed, - new ExceptionDetail( - new MessageDetail(TokenLogMessages.IDX10504), - ValidationErrorType.SecurityTokenInvalidSignature)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidSignature, + new MessageDetail( + TokenLogMessages.IDX10504, + LogHelper.MarkAsSecurityArtifact( + jsonWebToken.EncodedToken, + JwtTokenUtilities.SafeLogJwtToken)), + 0x123123, + null)); } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { - return new SignatureValidationResult( - ValidationFailureType.SignatureValidationFailed, - new ExceptionDetail( - new MessageDetail(TokenLogMessages.IDX10504, ex.ToString()), + return new(new TokenValidationError( ValidationErrorType.SecurityTokenInvalidSignature, + new MessageDetail( + TokenLogMessages.IDX10504, + LogHelper.MarkAsSecurityArtifact( + jsonWebToken.EncodedToken, + JwtTokenUtilities.SafeLogJwtToken)), + 0x123123, ex)); } finally @@ -273,7 +277,7 @@ private static SignatureValidationResult ValidateSignatureWithKey( } } - private static ExceptionDetail GetSignatureValidationFailureExceptionDetails( + private static TokenValidationError GetSignatureValidationError( JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration? configuration, @@ -293,7 +297,8 @@ private static ExceptionDetail GetSignatureValidationFailureExceptionDetails( JsonWebToken localJwtToken = jwtToken; // avoid closure on non-exceptional path bool isKidInTVP = keysInTokenValidationParameters.Any(x => x.KeyId.Equals(localJwtToken.Kid)); string keyLocation = isKidInTVP ? "TokenValidationParameters" : "Configuration"; - return new ExceptionDetail( + return new TokenValidationError( + ValidationErrorType.SecurityTokenSignatureKeyNotFound, new MessageDetail( TokenLogMessages.IDX10511, LogHelper.MarkAsNonPII(keysAttempted.ToString()), @@ -303,22 +308,26 @@ private static ExceptionDetail GetSignatureValidationFailureExceptionDetails( LogHelper.MarkAsNonPII(jwtToken.Kid), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - ValidationErrorType.SecurityTokenSignatureKeyNotFound); + 0x1232123, + null); } if (kidExists) - return new ExceptionDetail( + return new TokenValidationError( + ValidationErrorType.SecurityTokenSignatureKeyNotFound, new MessageDetail( - TokenLogMessages.IDX10503, // No match for kid found among the keys provided. + TokenLogMessages.IDX10503, LogHelper.MarkAsNonPII(jwtToken.Kid), LogHelper.MarkAsNonPII(keysAttempted.ToString()), LogHelper.MarkAsNonPII(numKeysInTokenValidationParameters), LogHelper.MarkAsNonPII(numKeysInConfiguration), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - ValidationErrorType.SecurityTokenSignatureKeyNotFound); + 0x1232123, + null); - return new ExceptionDetail( + return new TokenValidationError( + ValidationErrorType.SecurityTokenSignatureKeyNotFound, new MessageDetail( TokenLogMessages.IDX10517, // Kid is missing and no keys match. LogHelper.MarkAsNonPII(keysAttempted.ToString()), @@ -326,7 +335,8 @@ private static ExceptionDetail GetSignatureValidationFailureExceptionDetails( LogHelper.MarkAsNonPII(numKeysInConfiguration), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - ValidationErrorType.SecurityTokenSignatureKeyNotFound); + 0x1232123, + null); } private static void PopulateFailedResults( @@ -338,17 +348,17 @@ private static void PopulateFailedResults( { for (int i = 0; i < result.KeysAttempted.Count; i++) { - exceptionStrings.AppendLine(result.FailedResults[i].ExceptionDetail?.MessageDetail.Message ?? "Null"); + exceptionStrings.AppendLine(result.FailedResults[i].MessageDetail.Message); keysAttempted.AppendLine(result.KeysAttempted[i].ToString()); } } } private struct KeyMatchFailedResult( - IList failedResults, + IList failedResults, IList keysAttempted) { - public IList FailedResults = failedResults; + public IList FailedResults = failedResults; public IList KeysAttempted = keysAttempted; } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs index 487b3da597..4f6ce39fd5 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs @@ -33,7 +33,7 @@ public partial class JsonWebTokenHandler : TokenHandler /// Returned if 'token.Length' is greater than . /// Returned if is not a valid , /// Returned if the validationParameters.TokenReader delegate is not able to parse/read the token as a valid , - internal async Task ValidateTokenAsync( + internal async Task ValidateTokenAsync( string token, ValidationParameters validationParameters, CallContext callContext, @@ -41,15 +41,31 @@ internal async Task ValidateTokenAsync( { // These exceptions will be removed once we add ExceptionDetails to TokenValidationResult. if (string.IsNullOrEmpty(token)) - return new TokenValidationResult { Exception = LogHelper.LogArgumentNullException(nameof(token)), IsValid = false }; + return new ValidationResult( + null, + this, + validationParameters, + TokenValidationErrorCommon.NullParameter(nameof(token), tag: 0x121211)); if (validationParameters is null) - return new TokenValidationResult { Exception = LogHelper.LogArgumentNullException(nameof(validationParameters)), IsValid = false }; + return new ValidationResult( + null, + this, + validationParameters, + TokenValidationErrorCommon.NullParameter(nameof(validationParameters), tag: 0x121212)); if (token.Length > MaximumTokenSizeInBytes) - return new TokenValidationResult { Exception = LogHelper.LogExceptionMessage(new ArgumentException(LogHelper.FormatInvariant(TokenLogMessages.IDX10209, LogHelper.MarkAsNonPII(token.Length), LogHelper.MarkAsNonPII(MaximumTokenSizeInBytes)))), IsValid = false }; + return new ValidationResult( + null, + this, + validationParameters, + new TokenValidationError( + ValidationErrorType.InvalidArgument, + new MessageDetail(TokenLogMessages.IDX10209, LogHelper.MarkAsNonPII(token.Length), LogHelper.MarkAsNonPII(MaximumTokenSizeInBytes)), + Tag: 0x121213, + null)); - Result result = ReadToken(token, callContext); + Result result = ReadToken(token, callContext); if (result.IsSuccess) return await ValidateTokenAsync( result.Unwrap(), @@ -58,31 +74,44 @@ internal async Task ValidateTokenAsync( cancellationToken) .ConfigureAwait(false); - ExceptionDetail exceptionDetail = new ExceptionDetail(result.UnwrapError().MessageDetail, result.UnwrapError().ErrorType); - - return new TokenValidationResult - { - Exception = exceptionDetail.GetException(), - IsValid = false - }; + return new ValidationResult( + null, + this, + validationParameters, + result.UnwrapError()); } /// - internal async Task ValidateTokenAsync( + internal async Task ValidateTokenAsync( SecurityToken token, ValidationParameters validationParameters, CallContext callContext, CancellationToken? cancellationToken) { - // These exceptions will be removed once we add ExceptionDetails to TokenValidationResult. if (token is null) - throw LogHelper.LogArgumentNullException(nameof(token)); + return new ValidationResult( + token, + this, + validationParameters, + TokenValidationErrorCommon.NullParameter(nameof(token), tag: 0x121211)); if (validationParameters is null) - return new TokenValidationResult { Exception = LogHelper.LogArgumentNullException(nameof(validationParameters)), IsValid = false }; + return new ValidationResult( + token, + this, + validationParameters, + TokenValidationErrorCommon.NullParameter(nameof(validationParameters), tag: 0x121212)); if (token is not JsonWebToken jwt) - return new TokenValidationResult { Exception = LogHelper.LogArgumentException(nameof(token), $"{nameof(token)} must be a {nameof(JsonWebToken)}."), IsValid = false }; + return new ValidationResult( + token, + this, + validationParameters, + new TokenValidationError( + ValidationErrorType.InvalidArgument, + new MessageDetail(TokenLogMessages.IDX10001, nameof(token), nameof(JsonWebToken)), + Tag: 0x121214, + null)); return await InternalValidateTokenAsync( jwt, @@ -102,7 +131,7 @@ internal async Task ValidateTokenAsync( /// A that contains useful information for logging. /// A that can be used to request cancellation of the asynchronous operation. /// - private async ValueTask InternalValidateTokenAsync( + private async ValueTask InternalValidateTokenAsync( JsonWebToken jsonWebToken, ValidationParameters validationParameters, CallContext callContext, @@ -112,12 +141,12 @@ private async ValueTask InternalValidateTokenAsync( await GetCurrentConfigurationAsync(validationParameters) .ConfigureAwait(false); - InternalTokenValidationResult result = jsonWebToken.IsEncrypted ? + ValidationResult result = jsonWebToken.IsEncrypted ? await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration, callContext, cancellationToken).ConfigureAwait(false) : await ValidateJWSAsync(jsonWebToken, validationParameters, currentConfiguration, callContext, cancellationToken).ConfigureAwait(false); if (validationParameters.ConfigurationManager is null) - return result.ToTokenValidationResult(); + return result; if (result.IsValid) { @@ -125,10 +154,10 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration, if (currentConfiguration is not null) validationParameters.ConfigurationManager.LastKnownGoodConfiguration = currentConfiguration; - return result.ToTokenValidationResult(); + return result; } - if (TokenUtilities.IsRecoverableExceptionType(result.ExceptionDetail.Type)) + if (TokenUtilities.IsRecoverableErrorType(result.TokenValidationError?.ErrorType)) { // If we were still unable to validate, attempt to refresh the configuration and validate using it // but ONLY if the currentConfiguration is not null. We want to avoid refreshing the configuration on @@ -151,7 +180,7 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration, if (result.IsValid) { validationParameters.ConfigurationManager.LastKnownGoodConfiguration = currentConfiguration; - return result.ToTokenValidationResult(); + return result; } } } @@ -160,7 +189,7 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration, { validationParameters.RefreshBeforeValidation = false; validationParameters.ValidateWithLKG = true; - ValidationErrorType recoverableExceptionType = result.ExceptionDetail.Type; + ValidationErrorType recoverableExceptionType = result.TokenValidationError?.ErrorType ?? ValidationErrorType.Unknown; BaseConfiguration[] validConfigurations = validationParameters.ConfigurationManager.GetValidLkgConfigurations(); for (int i = 0; i < validConfigurations.Length; i++) @@ -174,118 +203,185 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration, await ValidateJWSAsync(jsonWebToken, validationParameters, currentConfiguration, callContext, cancellationToken).ConfigureAwait(false); if (result.IsValid) - return result.ToTokenValidationResult(); + return result; } } } } - return result.ToTokenValidationResult(); + return result; } - private async ValueTask ValidateJWEAsync( + private async ValueTask ValidateJWEAsync( JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration configuration, CallContext callContext, CancellationToken? cancellationToken) { - InternalTokenValidationResult internalResult = new InternalTokenValidationResult(jwtToken, this); + Result decryptionResult = DecryptToken( + jwtToken, validationParameters, configuration, callContext); + + if (!decryptionResult.IsSuccess) + return new ValidationResult(jwtToken, this, validationParameters, decryptionResult.UnwrapError()); - TokenDecryptionResult decryptionResult = DecryptToken(jwtToken, validationParameters, configuration, callContext); - if (!internalResult.AddResult(decryptionResult)) - return internalResult; + Result readResult = ReadToken(decryptionResult.Unwrap(), callContext); - Result result = ReadToken(decryptionResult.DecryptedToken(), callContext); - if (!result.IsSuccess) - return internalResult; - //TokenReadingResult readingResult = ReadToken(decryptionResult.DecryptedToken(), callContext); - //if (!internalResult.AddResult(readingResult)) - // return internalResult; + if (!readResult.IsSuccess) + return new ValidationResult(jwtToken, this, validationParameters, readResult.UnwrapError()); - JsonWebToken decryptedToken = result.Unwrap() as JsonWebToken; + JsonWebToken decryptedToken = readResult.Unwrap() as JsonWebToken; - InternalTokenValidationResult jwsResult = + ValidationResult validationResult = await ValidateJWSAsync(decryptedToken, validationParameters, configuration, callContext, cancellationToken) .ConfigureAwait(false); - if (!internalResult.Merge(jwsResult)) - return internalResult; + if (!validationResult.IsValid) + return validationResult; - jwtToken.InnerToken = internalResult.SecurityToken as JsonWebToken; - jwtToken.Payload = (internalResult.SecurityToken as JsonWebToken).Payload; + jwtToken.InnerToken = validationResult.SecurityToken as JsonWebToken; + jwtToken.Payload = (validationResult.SecurityToken as JsonWebToken).Payload; - return internalResult; + return validationResult; } - private async ValueTask ValidateJWSAsync( + private async ValueTask ValidateJWSAsync( JsonWebToken jsonWebToken, ValidationParameters validationParameters, BaseConfiguration configuration, CallContext callContext, CancellationToken? cancellationToken) { - if (validationParameters.TransformBeforeSignatureValidation is not null) - jsonWebToken = validationParameters.TransformBeforeSignatureValidation(jsonWebToken, validationParameters) as JsonWebToken; - - InternalTokenValidationResult internalResult = new InternalTokenValidationResult(jsonWebToken, this); - DateTime? expires = jsonWebToken.HasPayloadClaim(JwtRegisteredClaimNames.Exp) ? jsonWebToken.ValidTo : null; DateTime? notBefore = jsonWebToken.HasPayloadClaim(JwtRegisteredClaimNames.Nbf) ? jsonWebToken.ValidFrom : null; - if (!internalResult.AddResult(validationParameters.LifetimeValidator( - notBefore, expires, jsonWebToken, validationParameters, callContext))) - return internalResult; + Result lifetimeValidationResult = validationParameters.LifetimeValidator( + notBefore, expires, jsonWebToken, validationParameters, callContext); + + if (!lifetimeValidationResult.IsSuccess) + return new ValidationResult(jsonWebToken, this, validationParameters, lifetimeValidationResult.UnwrapError()); if (jsonWebToken.Audiences is not IList tokenAudiences) tokenAudiences = jsonWebToken.Audiences.ToList(); - if (!internalResult.AddResult(validationParameters.AudienceValidator( - tokenAudiences, jsonWebToken, validationParameters, callContext))) - return internalResult; + Result audienceValidationResult = validationParameters.AudienceValidator( + tokenAudiences, jsonWebToken, validationParameters, callContext); - if (!internalResult.AddResult(await validationParameters.IssuerValidatorAsync( + if (!audienceValidationResult.IsSuccess) + return new ValidationResult(jsonWebToken, this, validationParameters, audienceValidationResult.UnwrapError()) + { + ValidatedLifetime = lifetimeValidationResult.Unwrap() + }; + + Result issuerValidationResult = await validationParameters.IssuerValidatorAsync( jsonWebToken.Issuer, jsonWebToken, validationParameters, callContext, cancellationToken) - .ConfigureAwait(false))) - return internalResult; + .ConfigureAwait(false); + + if (!issuerValidationResult.IsSuccess) + return new ValidationResult(jsonWebToken, this, validationParameters, issuerValidationResult.UnwrapError()) + { + ValidatedLifetime = lifetimeValidationResult.Unwrap(), + ValidatedAudience = audienceValidationResult.Unwrap() + }; - if (!internalResult.AddResult(validationParameters.TokenReplayValidator( - expires, jsonWebToken.EncodedToken, validationParameters, callContext))) - return internalResult; + Result replayValidationResult = validationParameters.TokenReplayValidator( + expires, jsonWebToken.EncodedToken, validationParameters, callContext); + if (!replayValidationResult.IsSuccess) + return new ValidationResult(jsonWebToken, this, validationParameters, replayValidationResult.UnwrapError()) + { + ValidatedLifetime = lifetimeValidationResult.Unwrap(), + ValidatedAudience = audienceValidationResult.Unwrap(), + ValidatedIssuer = issuerValidationResult.Unwrap() + }; + + ValidationResult actorValidationResult = null; // actor validation if (validationParameters.ValidateActor && !string.IsNullOrWhiteSpace(jsonWebToken.Actor)) { - Result actorReadingResult = ReadToken(jsonWebToken.Actor, callContext); + Result actorReadingResult = ReadToken(jsonWebToken.Actor, callContext); if (!actorReadingResult.IsSuccess) - return internalResult; + return new ValidationResult(jsonWebToken, this, validationParameters, actorReadingResult.UnwrapError()) + { + ValidatedLifetime = lifetimeValidationResult.Unwrap(), + ValidatedAudience = audienceValidationResult.Unwrap(), + ValidatedIssuer = issuerValidationResult.Unwrap(), + ValidatedTokenReplayExpirationTime = replayValidationResult.Unwrap() + }; JsonWebToken actorToken = actorReadingResult.Unwrap() as JsonWebToken; ValidationParameters actorParameters = validationParameters.ActorValidationParameters; - InternalTokenValidationResult actorValidationResult = + actorValidationResult = await ValidateJWSAsync(actorToken, actorParameters, configuration, callContext, cancellationToken) .ConfigureAwait(false); // Consider adding a new ValidationResult type for actor validation // that wraps the actorValidationResult.ValidationResults - if (!internalResult.AddResults(actorValidationResult.ValidationResults)) - return internalResult; + if (!actorValidationResult.IsValid) + return new ValidationResult(jsonWebToken, this, validationParameters, actorValidationResult.TokenValidationError) + { + ValidatedLifetime = lifetimeValidationResult.Unwrap(), + ValidatedAudience = audienceValidationResult.Unwrap(), + ValidatedIssuer = issuerValidationResult.Unwrap(), + ValidatedTokenReplayExpirationTime = replayValidationResult.Unwrap(), + ActorValidationResult = actorValidationResult + }; } - if (!internalResult.AddResult(validationParameters.TypeValidator( - jsonWebToken.Typ, jsonWebToken, validationParameters, callContext))) - return internalResult; + Result typeValidationResult = validationParameters.TypeValidator( + jsonWebToken.Typ, jsonWebToken, validationParameters, callContext); - // The signature validation delegate is yet to be migrated to ValidationParameters. - if (!internalResult.AddResult(ValidateSignature( - jsonWebToken, validationParameters, configuration, callContext))) - return internalResult; + if (!typeValidationResult.IsSuccess) + return new ValidationResult(jsonWebToken, this, validationParameters, typeValidationResult.UnwrapError()) + { + ValidatedLifetime = lifetimeValidationResult.Unwrap(), + ValidatedAudience = audienceValidationResult.Unwrap(), + ValidatedIssuer = issuerValidationResult.Unwrap(), + ValidatedTokenReplayExpirationTime = replayValidationResult.Unwrap(), + ActorValidationResult = actorValidationResult + }; - if (!internalResult.AddResult(validationParameters.IssuerSigningKeyValidator( - jsonWebToken.SigningKey, jsonWebToken, validationParameters, configuration, callContext))) - return internalResult; + // The signature validation delegate is yet to be migrated to ValidationParameters. + Result signatureValidationResult = ValidateSignature( + jsonWebToken, validationParameters, configuration, callContext); - return internalResult; + if (!signatureValidationResult.IsSuccess) + return new ValidationResult(jsonWebToken, this, validationParameters, signatureValidationResult.UnwrapError()) + { + ValidatedLifetime = lifetimeValidationResult.Unwrap(), + ValidatedAudience = audienceValidationResult.Unwrap(), + ValidatedIssuer = issuerValidationResult.Unwrap(), + ValidatedTokenReplayExpirationTime = replayValidationResult.Unwrap(), + ActorValidationResult = actorValidationResult, + ValidatedTokenType = typeValidationResult.Unwrap() + }; + + Result issuerSigningKeyValidationResult = validationParameters.IssuerSigningKeyValidator( + signatureValidationResult.Unwrap(), jsonWebToken, validationParameters, configuration, callContext); + + if (!issuerSigningKeyValidationResult.IsSuccess) + return new ValidationResult(jsonWebToken, this, validationParameters, issuerSigningKeyValidationResult.UnwrapError()) + { + ValidatedLifetime = lifetimeValidationResult.Unwrap(), + ValidatedAudience = audienceValidationResult.Unwrap(), + ValidatedIssuer = issuerValidationResult.Unwrap(), + ValidatedTokenReplayExpirationTime = replayValidationResult.Unwrap(), + ActorValidationResult = actorValidationResult, + ValidatedTokenType = typeValidationResult.Unwrap(), + ValidatedSigningKey = signatureValidationResult.Unwrap() + }; + + return new(jsonWebToken, this, validationParameters) + { + ValidatedLifetime = lifetimeValidationResult.Unwrap(), + ValidatedAudience = audienceValidationResult.Unwrap(), + ValidatedIssuer = issuerValidationResult.Unwrap(), + ValidatedTokenReplayExpirationTime = replayValidationResult.Unwrap(), + ActorValidationResult = actorValidationResult, + ValidatedTokenType = typeValidationResult.Unwrap(), + ValidatedSigningKey = signatureValidationResult.Unwrap(), + ValidatedSigningKeyLifetime = issuerSigningKeyValidationResult.Unwrap() + }; } private static async Task GetCurrentConfigurationAsync(ValidationParameters validationParameters) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs index b64095a788..2cb41ffaa4 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs @@ -5,7 +5,7 @@ using System.Text; using Microsoft.IdentityModel.Tokens; //using Microsoft.IdentityModel.Logging; -//using Microsoft.IdentityModel.Abstractions; +using Microsoft.IdentityModel.Abstractions; using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages; namespace Microsoft.IdentityModel.JsonWebTokens @@ -20,31 +20,17 @@ public partial class JwtTokenUtilities /// The decryption parameters container. /// The call context used for logging. /// The decrypted, and if the 'zip' claim is set, decompressed string representation of the token. - internal static TokenDecryptionResult DecryptJwtToken( + internal static Result DecryptJwtToken( JsonWebToken jsonWebToken, ValidationParameters validationParameters, JwtTokenDecryptionParameters decryptionParameters, CallContext callContext) { if (validationParameters == null) - return new TokenDecryptionResult( - jsonWebToken, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - TokenLogMessages.IDX10000, - nameof(validationParameters)), - ValidationErrorType.ArgumentNull)); + return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123141)); if (decryptionParameters == null) - return new TokenDecryptionResult( - jsonWebToken, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - TokenLogMessages.IDX10000, - nameof(decryptionParameters)), - ValidationErrorType.ArgumentNull)); + return new(TokenValidationErrorCommon.NullParameter(nameof(decryptionParameters), 0x123142)); bool decryptionSucceeded = false; bool algorithmNotSupportedByCryptoProvider = false; @@ -78,10 +64,10 @@ internal static TokenDecryptionResult DecryptJwtToken( continue; } - AlgorithmValidationResult result = validationParameters.AlgorithmValidator(zipAlgorithm, key, jsonWebToken, validationParameters, callContext); - if (!result.IsValid) + Result result = validationParameters.AlgorithmValidator(zipAlgorithm, key, jsonWebToken, validationParameters, callContext); + if (!result.IsSuccess) { - (exceptionStrings ??= new StringBuilder()).AppendLine(result.ExceptionDetail.MessageDetail.Message); + (exceptionStrings ??= new StringBuilder()).AppendLine(result.UnwrapError().MessageDetail.Message); continue; } @@ -110,15 +96,12 @@ internal static TokenDecryptionResult DecryptJwtToken( } if (!decryptionSucceeded) - return new TokenDecryptionResult( - jsonWebToken, - ValidationFailureType.TokenDecryptionFailed, - GetDecryptionExceptionDetail( - decryptionParameters, - algorithmNotSupportedByCryptoProvider, - exceptionStrings, - keysAttempted, - callContext)); + return new(GetDecryptionError( + decryptionParameters, + algorithmNotSupportedByCryptoProvider, + exceptionStrings, + keysAttempted, + callContext)); try { @@ -128,21 +111,17 @@ internal static TokenDecryptionResult DecryptJwtToken( else decodedString = decryptionParameters.DecompressionFunction(decryptedTokenBytes, zipAlgorithm, decryptionParameters.MaximumDeflateSize); - return new TokenDecryptionResult(decodedString, jsonWebToken); + return new(decodedString); } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { - return new TokenDecryptionResult( - jsonWebToken, - ValidationFailureType.TokenDecryptionFailed, - new ExceptionDetail( - new MessageDetail( - TokenLogMessages.IDX10679, - zipAlgorithm), - ValidationErrorType.SecurityTokenDecompressionFailed, - ex)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenDecompressionFailed, + new MessageDetail(TokenLogMessages.IDX10679, zipAlgorithm), + 0x123123, + ex)); } } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs index 81f9fa944b..fb7f34a9b0 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs @@ -330,12 +330,16 @@ internal static string DecryptJwtToken( } if (!decryptionSucceeded) - throw GetDecryptionExceptionDetail( + { + TokenValidationError error = GetDecryptionError( decryptionParameters, algorithmNotSupportedByCryptoProvider, exceptionStrings, keysAttempted, - null).GetException(); + null); + + throw LogHelper.LogExceptionMessage(ExceptionDetail.ExceptionFromType(error.ErrorType, error.MessageDetail, null)); + } try { @@ -350,7 +354,7 @@ internal static string DecryptJwtToken( } } - private static ExceptionDetail GetDecryptionExceptionDetail( + private static TokenValidationError GetDecryptionError( JwtTokenDecryptionParameters decryptionParameters, bool algorithmNotSupportedByCryptoProvider, StringBuilder exceptionStrings, @@ -360,28 +364,31 @@ private static ExceptionDetail GetDecryptionExceptionDetail( #pragma warning restore CA1801 // Review unused parameters { if (keysAttempted is not null) - return new ExceptionDetail( + return new TokenValidationError( + ValidationErrorType.SecurityTokenDecryptionFailed, new MessageDetail( TokenLogMessages.IDX10603, keysAttempted.ToString(), exceptionStrings?.ToString() ?? string.Empty, LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken)), - ValidationErrorType.SecurityTokenDecryptionFailed, + Tag: 0x123456, null); else if (algorithmNotSupportedByCryptoProvider) - return new ExceptionDetail( + return new TokenValidationError( + ValidationErrorType.SecurityTokenDecryptionFailed, new MessageDetail( TokenLogMessages.IDX10619, LogHelper.MarkAsNonPII(decryptionParameters.Alg), LogHelper.MarkAsNonPII(decryptionParameters.Enc)), - ValidationErrorType.SecurityTokenDecryptionFailed, + Tag: 0x123456, null); else - return new ExceptionDetail( + return new TokenValidationError( + ValidationErrorType.SecurityTokenDecryptionFailed, new MessageDetail( TokenLogMessages.IDX10609, LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken)), - ValidationErrorType.SecurityTokenDecryptionFailed, + Tag: 0x123456, null); } diff --git a/src/Microsoft.IdentityModel.Tokens/Delegates.cs b/src/Microsoft.IdentityModel.Tokens/Delegates.cs index 0587164690..d4ab3d76d8 100644 --- a/src/Microsoft.IdentityModel.Tokens/Delegates.cs +++ b/src/Microsoft.IdentityModel.Tokens/Delegates.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Microsoft.IdentityModel.JsonWebTokens.Results; +using Microsoft.IdentityModel.Abstractions; namespace Microsoft.IdentityModel.Tokens { @@ -205,7 +205,7 @@ namespace Microsoft.IdentityModel.Tokens /// The to be used for logging. /// This method is not expected to throw. /// The validated . - internal delegate SignatureValidationResult SignatureValidatorDelegate(SecurityToken token, ValidationParameters validationParameters, BaseConfiguration? configuration, CallContext? callContext); + internal delegate Result SignatureValidatorDelegate(SecurityToken token, ValidationParameters validationParameters, BaseConfiguration? configuration, CallContext? callContext); /// /// Transforms the security token before signature validation. diff --git a/src/Microsoft.IdentityModel.Tokens/LogMessages.cs b/src/Microsoft.IdentityModel.Tokens/LogMessages.cs index ec1fbdf345..460a9012d8 100644 --- a/src/Microsoft.IdentityModel.Tokens/LogMessages.cs +++ b/src/Microsoft.IdentityModel.Tokens/LogMessages.cs @@ -14,6 +14,7 @@ internal static class LogMessages #pragma warning disable 1591 // general public const string IDX10000 = "IDX10000: The parameter '{0}' cannot be a 'null' or an empty object. "; + public const string IDX10001 = "IDX10001: Invalid argument '{0}'. Argument must be of type '{1}'."; // properties, configuration public const string IDX10101 = "IDX10101: MaximumTokenSizeInBytes must be greater than zero. value: '{0}'"; diff --git a/src/Microsoft.IdentityModel.Tokens/TokenUtilities.cs b/src/Microsoft.IdentityModel.Tokens/TokenUtilities.cs index c609529e9f..b676725f41 100644 --- a/src/Microsoft.IdentityModel.Tokens/TokenUtilities.cs +++ b/src/Microsoft.IdentityModel.Tokens/TokenUtilities.cs @@ -250,19 +250,21 @@ internal static IEnumerable MergeClaims(IEnumerable claims, IEnume /// true if the exception is certain types of exceptions otherwise, false. internal static bool IsRecoverableException(Exception exception) { - return IsRecoverableExceptionType(ExceptionTypeForException(exception)); + return IsRecoverableErrorType(ErrorTypeForException(exception)); } /// /// Check whether the given exception type is recoverable by LKG. /// - /// The exception type to check. + /// The exception type to check. /// true if the exception is certain types of exceptions otherwise, false. - internal static bool IsRecoverableExceptionType(ValidationErrorType exceptionType) + internal static bool IsRecoverableErrorType(ValidationErrorType? errorType) { - return exceptionType == ValidationErrorType.SecurityTokenInvalidSignature - || exceptionType == ValidationErrorType.SecurityTokenInvalidIssuer - || exceptionType == ValidationErrorType.SecurityTokenSignatureKeyNotFound; + ValidationErrorType typeToCheck = errorType ?? ValidationErrorType.Unknown; + + return typeToCheck == ValidationErrorType.SecurityTokenInvalidSignature + || typeToCheck == ValidationErrorType.SecurityTokenInvalidIssuer + || typeToCheck == ValidationErrorType.SecurityTokenSignatureKeyNotFound; } /// @@ -277,7 +279,7 @@ internal static bool IsRecoverableConfiguration( string kid, BaseConfiguration currentConfiguration, BaseConfiguration lkgConfiguration, Exception currentException) { return IsRecoverableConfigurationAndExceptionType( - kid, currentConfiguration, lkgConfiguration, ExceptionTypeForException(currentException)); + kid, currentConfiguration, lkgConfiguration, ErrorTypeForException(currentException)); } /// @@ -314,7 +316,7 @@ internal static bool IsRecoverableConfigurationAndExceptionType( return false; } - static ValidationErrorType ExceptionTypeForException(Exception exception) + static ValidationErrorType ErrorTypeForException(Exception exception) { if (exception is SecurityTokenInvalidSignatureException) return ValidationErrorType.SecurityTokenInvalidSignature; diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/AlgorithmValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/AlgorithmValidationResult.cs deleted file mode 100644 index 1946ee3b02..0000000000 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/AlgorithmValidationResult.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -#nullable enable -namespace Microsoft.IdentityModel.Tokens -{ - /// - /// Contains the result of validating the Algorithm of a . - /// The contains a collection of for each step in the token validation. - /// - internal class AlgorithmValidationResult : ValidationResult - { - private Exception? _exception; - private const string TokenSource = "Microsoft.IdentityModel.Tokens"; - - /// - /// Creates an instance of . - /// - /// The algorithm to be validated. - public AlgorithmValidationResult(string? algorithm) - : base(ValidationFailureType.ValidationSucceeded) - { - Algorithm = algorithm; - IsValid = true; - } - - /// - /// Creates an instance of - /// - /// The algorithm to be validated. - /// is the that occurred during validation. - /// is the that occurred during validation. - public AlgorithmValidationResult(string? algorithm, ValidationFailureType validationFailure, ExceptionDetail exceptionDetail) - : base(validationFailure, exceptionDetail) - { - Algorithm = algorithm; - IsValid = false; - } - - /// - /// Gets the that occurred during validation. - /// - public override Exception? Exception - { - get - { - if (_exception != null || ExceptionDetail == null) - return _exception; - - HasValidOrExceptionWasRead = true; - _exception = ExceptionDetail.GetException(); - if (_exception is SecurityTokenInvalidAlgorithmException securityTokenInvalidAlgorithmException) - { - securityTokenInvalidAlgorithmException.InvalidAlgorithm = Algorithm; - securityTokenInvalidAlgorithmException.Source = TokenSource; - } - - return _exception; - } - } - - /// - /// Gets the algorithm used to sign the token. - /// - public string? Algorithm { get; } - - } -} -#nullable restore diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/AudienceValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/AudienceValidationResult.cs deleted file mode 100644 index 024cca68ba..0000000000 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/AudienceValidationResult.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; - -namespace Microsoft.IdentityModel.Tokens -{ - /// - /// Contains the result of validating the audiences from a . - /// The contains a collection of for each step in the token validation. - /// - internal class AudienceValidationResult : ValidationResult - { - private Exception _exception; - - /// - /// Creates an instance of . - /// - /// is the audience that was validated successfully. - public AudienceValidationResult(string audience) : base(ValidationFailureType.ValidationSucceeded) - { - IsValid = true; - Audience = audience; - } - - /// - /// Creates an instance of - /// - /// is the audience that was intended to be validated. - /// is the that occurred during validation. - /// is the that occurred during validation. - public AudienceValidationResult(string audience, ValidationFailureType validationFailure, ExceptionDetail exceptionDetail) - : base(validationFailure, exceptionDetail) - { - IsValid = false; - Audience = audience; - } - - /// - /// Gets the that occurred during validation. - /// - public override Exception Exception - { - get - { - if (_exception != null || ExceptionDetail == null) - return _exception; - - HasValidOrExceptionWasRead = true; - _exception = ExceptionDetail.GetException(); - if (_exception is SecurityTokenInvalidAudienceException securityTokenInvalidAudienceException) - { - securityTokenInvalidAudienceException.InvalidAudience = Audience; - securityTokenInvalidAudienceException.ExceptionDetail = ExceptionDetail; - securityTokenInvalidAudienceException.Source = "Microsoft.IdentityModel.Tokens"; - } - - return _exception; - } - } - - /// - /// Gets the audience that was validated or intended to be validated. - /// - public string Audience { get; } - } -} diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs index c2a442f1d9..89b959f266 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using Microsoft.IdentityModel.Logging; namespace Microsoft.IdentityModel.Tokens { @@ -40,12 +39,10 @@ public ExceptionDetail(MessageDetail messageDetail, ValidationErrorType exceptio /// Creates an instance of an using /// /// An instantance of an Exception. - public Exception GetException() => ExceptionFromType(Type, InnerException); + public Exception GetException() => ExceptionFromType(Type, MessageDetail, InnerException); internal static ExceptionDetail NullParameter(string parameterName) => new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII(parameterName)), + MessageDetail.NullParameter(parameterName), ValidationErrorType.ArgumentNull); /// @@ -68,50 +65,55 @@ public ExceptionDetail(MessageDetail messageDetail, ValidationErrorType exceptio /// public IList StackFrames { get; } = []; - public Exception ExceptionFromType(ValidationErrorType exceptionType, Exception innerException) + public static Exception ExceptionFromType( + ValidationErrorType exceptionType, + MessageDetail messageDetail, + Exception innerException) { switch (exceptionType) { case ValidationErrorType.ArgumentNull: - return new ArgumentNullException(MessageDetail.Message, innerException); + return new ArgumentNullException(messageDetail.Message, innerException); + case ValidationErrorType.InvalidArgument: + return new ArgumentException(messageDetail.Message, innerException); case ValidationErrorType.InvalidOperation: - return new InvalidOperationException(MessageDetail.Message, innerException); + return new InvalidOperationException(messageDetail.Message, innerException); case ValidationErrorType.SecurityToken: - return new SecurityTokenException(MessageDetail.Message, innerException); + return new SecurityTokenException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenDecompressionFailed: - return new SecurityTokenDecompressionFailedException(MessageDetail.Message, innerException); + return new SecurityTokenDecompressionFailedException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenDecryptionFailed: - return new SecurityTokenDecryptionFailedException(MessageDetail.Message, innerException); + return new SecurityTokenDecryptionFailedException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenExpired: - return new SecurityTokenExpiredException(MessageDetail.Message, innerException); + return new SecurityTokenExpiredException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenInvalidAudience: - return new SecurityTokenInvalidAudienceException(MessageDetail.Message, innerException); + return new SecurityTokenInvalidAudienceException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenInvalidAlgorithm: - return new SecurityTokenInvalidAlgorithmException(MessageDetail.Message, innerException); + return new SecurityTokenInvalidAlgorithmException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenInvalidIssuer: - return new SecurityTokenInvalidIssuerException(MessageDetail.Message, innerException); + return new SecurityTokenInvalidIssuerException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenInvalidLifetime: - return new SecurityTokenInvalidLifetimeException(MessageDetail.Message, innerException); + return new SecurityTokenInvalidLifetimeException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenInvalidSignature: - return new SecurityTokenInvalidSignatureException(MessageDetail.Message, innerException); + return new SecurityTokenInvalidSignatureException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenInvalidSigningKey: - return new SecurityTokenInvalidSigningKeyException(MessageDetail.Message, innerException); + return new SecurityTokenInvalidSigningKeyException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenInvalidType: - return new SecurityTokenInvalidTypeException(MessageDetail.Message, innerException); + return new SecurityTokenInvalidTypeException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenKeyWrap: - return new SecurityTokenKeyWrapException(MessageDetail.Message, innerException); + return new SecurityTokenKeyWrapException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenMalformed: - return new SecurityTokenMalformedException(MessageDetail.Message, innerException); + return new SecurityTokenMalformedException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenNoExpiration: - return new SecurityTokenNoExpirationException(MessageDetail.Message, innerException); + return new SecurityTokenNoExpirationException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenNotYetValid: - return new SecurityTokenNotYetValidException(MessageDetail.Message, innerException); + return new SecurityTokenNotYetValidException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenReplayDetected: - return new SecurityTokenReplayDetectedException(MessageDetail.Message, innerException); + return new SecurityTokenReplayDetectedException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenReplayAddFailed: - return new SecurityTokenReplayAddFailedException(MessageDetail.Message, innerException); + return new SecurityTokenReplayAddFailedException(messageDetail.Message, innerException); case ValidationErrorType.SecurityTokenSignatureKeyNotFound: - return new SecurityTokenSignatureKeyNotFoundException(MessageDetail.Message, innerException); + return new SecurityTokenSignatureKeyNotFoundException(messageDetail.Message, innerException); default: throw new ArgumentException("Invalid ExceptionType."); } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/MessageDetail.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/MessageDetail.cs index 2ca5dcafb8..188e3a51b8 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/MessageDetail.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/MessageDetail.cs @@ -8,7 +8,7 @@ namespace Microsoft.IdentityModel.Tokens /// /// Contains information about a message that is used to generate a message for logging or exceptions. /// - internal struct MessageDetail + internal class MessageDetail { private string _message; @@ -26,6 +26,9 @@ public MessageDetail(string formatString, params object[] parameters) Parameters = parameters; } + public static MessageDetail NullParameter(string parameterName) + => new MessageDetail(LogMessages.IDX10000, LogHelper.MarkAsNonPII(parameterName)); + /// /// Gets the formatted message. /// diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/InternalTokenValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/InternalTokenValidationResult.cs deleted file mode 100644 index 41570c1f65..0000000000 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/InternalTokenValidationResult.cs +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; - -namespace Microsoft.IdentityModel.Tokens -{ -#nullable enable - /// - /// Internal class used to track the results of token validation and to provide a way to merge results. - /// Once all validation is complete, the results can be converted to a TokenValidationResult. - /// - internal class InternalTokenValidationResult - { - private bool _isValid; - private SecurityToken? _securityToken; - private TokenHandler _tokenHandler; - private List _validationResults = new List(20); - - /// - /// Creates a new instance of to aggregate validation results. - /// - /// The being validated. - /// The performing the validation. - /// - public InternalTokenValidationResult(SecurityToken? securityToken, TokenHandler tokenHandler) - { - _securityToken = securityToken; - _tokenHandler = tokenHandler ?? throw new ArgumentNullException(nameof(tokenHandler)); - _isValid = true; - } - - /// - /// Adds a to the aggregated list of validation results. - /// - /// The to store. - /// The current IsValid value for the validation. - /// - public bool AddResult(ValidationResult validationResult) - { - if (validationResult == null) - throw new ArgumentNullException(nameof(validationResult)); - - _validationResults.Add(validationResult); - _isValid = _isValid && validationResult.IsValid; - - return IsValid; - } - - /// - /// Adds a list of to the aggregated list of validation results. - /// - /// The list of to store. - /// The current IsValid value for the validation. - /// - public bool AddResults(IList validationResults) - { - if (validationResults == null) - throw new ArgumentNullException(nameof(validationResults)); - - _validationResults.AddRange(validationResults); - for (int i = 0; i < validationResults.Count; i++) - _isValid = _isValid && validationResults[i].IsValid; - - return IsValid; - } - - /// - /// Gets the for the first failed validation result. - /// - public ExceptionDetail? ExceptionDetail - { - get - { - if (ValidationResults.Count == 0) - return null; - - // Iterate in reverse since the failure should be the last result - for (int i = ValidationResults.Count - 1; i >= 0; i--) - { - ValidationResult validationResult = ValidationResults[i]; - if (validationResult.ExceptionDetail != null) - return validationResult.ExceptionDetail; - } - - return null; - } - } - - /// - /// Gets a value indicating whether the token is valid. - /// - public bool IsValid => _isValid; - - /// - /// Merges the results of another into this instance. - /// Updates the and in case they changed. - /// - /// The to be merged. - /// - public bool Merge(InternalTokenValidationResult other) - { - _securityToken = other._securityToken; - _tokenHandler = other._tokenHandler; - - return AddResults(other.ValidationResults); - } - - /// - /// Gets the being validated. - /// - public SecurityToken? SecurityToken => _securityToken; - - /// - /// Returns a based on the aggregated validation results. - /// - /// The containing the result of aggregating all the individual results. - public TokenValidationResult ToTokenValidationResult() - { - if (IsValid) - { - // TokenValidationResult uses TokenValidationParameters to create ClaimsIdentity. - // We need to figure the best way to refactor that, ideally without creating a new TokenValidationResult class. - return new TokenValidationResult( - _securityToken, _tokenHandler, new TokenValidationParameters(), "issuer", _validationResults) - { - IsValid = true - }; - } - - return new TokenValidationResult - { - IsValid = false, - Exception = ExceptionDetail?.GetException(), // Need to introduce ExceptionDetail to TokenValidationResult - }; - } - - /// - /// Gets the list of that were aggregated. - /// - public IList ValidationResults => _validationResults; - } -#nullable restore -} diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/IssuerValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/IssuerValidationResult.cs deleted file mode 100644 index 292eacfab1..0000000000 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/IssuerValidationResult.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; - -namespace Microsoft.IdentityModel.Tokens -{ - /// - /// Contains the result of validating a issuer. - /// The contains a collection of for each step in the token validation. - /// - internal class IssuerValidationResult : ValidationResult - { - internal enum ValidationSource - { - NotValidated = 0, - IssuerIsConfigurationIssuer, - IssuerIsValidIssuer, - IssuerIsAmongValidIssuers - } - - private Exception _exception; - - /// - /// Creates an instance of - /// - /// is the issuer that was validated successfully. - /// is the indicating how this issuer was validated. - public IssuerValidationResult(string issuer, ValidationSource source = ValidationSource.NotValidated) - : base(ValidationFailureType.ValidationSucceeded) - { - Issuer = issuer; - IsValid = true; - Source = source; - } - - /// - /// Creates an instance of - /// - /// is the issuer that was intended to be validated. - /// is the that occurred during validation. - /// is the that occurred during validation. - /// is the indicating how this issuer was validated. - public IssuerValidationResult(string issuer, ValidationFailureType validationFailure, ExceptionDetail exceptionDetail, ValidationSource source = ValidationSource.NotValidated) - : base(validationFailure, exceptionDetail) - { - Issuer = issuer; - IsValid = false; - Source = source; - } - - /// - /// Gets the that occurred during validation. - /// - public override Exception Exception - { - get - { - if (_exception != null || ExceptionDetail == null) - return _exception; - - HasValidOrExceptionWasRead = true; - _exception = ExceptionDetail.GetException(); - SecurityTokenInvalidIssuerException securityTokenInvalidIssuerException = _exception as SecurityTokenInvalidIssuerException; - if (securityTokenInvalidIssuerException != null) - { - securityTokenInvalidIssuerException.InvalidIssuer = Issuer; - securityTokenInvalidIssuerException.ExceptionDetail = ExceptionDetail; - securityTokenInvalidIssuerException.Source = "Microsoft.IdentityModel.Tokens"; - } - - return _exception; - } - } - - /// - /// Gets the issuer that was validated or intended to be validated. - /// - public string Issuer { get; } - - public ValidationSource Source { get; } - } -} diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/LifetimeValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/LifetimeValidationResult.cs deleted file mode 100644 index f40608a574..0000000000 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/LifetimeValidationResult.cs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -#nullable enable -namespace Microsoft.IdentityModel.Tokens -{ - /// - /// Contains the result of validating the lifetime of a . - /// The contains a collection of for each step in the token validation. - /// - internal class LifetimeValidationResult : ValidationResult - { - private Exception? _exception; - - /// - /// Creates an instance of - /// - /// is the date from which the token that was validated successfully is valid. - /// is the expiration date for the token that was validated successfully. - public LifetimeValidationResult(DateTime? notBefore, DateTime? expires) - : base(ValidationFailureType.ValidationSucceeded) - { - NotBefore = notBefore; - Expires = expires; - IsValid = true; - } - - /// - /// Creates an instance of - /// - /// is the date from which the token is valid. - /// is the expiration date for the token. - /// is the that occurred during validation. - /// is the that occurred during validation. - public LifetimeValidationResult(DateTime? notBefore, DateTime? expires, ValidationFailureType validationFailure, ExceptionDetail exceptionDetail) - : base(validationFailure, exceptionDetail) - { - NotBefore = notBefore; - Expires = expires; - IsValid = false; - } - - /// - /// Gets the that occurred during validation. - /// - public override Exception? Exception - { - get - { - if (_exception != null || ExceptionDetail == null) - return _exception; - - HasValidOrExceptionWasRead = true; - _exception = ExceptionDetail.GetException(); - if (_exception is SecurityTokenInvalidLifetimeException securityTokenInvalidLifetimeException) - { - securityTokenInvalidLifetimeException.NotBefore = NotBefore; - securityTokenInvalidLifetimeException.Expires = Expires; - securityTokenInvalidLifetimeException.Source = "Microsoft.IdentityModel.Tokens"; - } - - return _exception; - } - } - - /// - /// Gets the date from which the token is valid. - /// - public DateTime? NotBefore { get; } - - /// - /// Gets the expiration date for the token. - /// - public DateTime? Expires { get; } - } -} -#nullable restore diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ReplayValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ReplayValidationResult.cs deleted file mode 100644 index dfaa0439b6..0000000000 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ReplayValidationResult.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; - -#nullable enable -namespace Microsoft.IdentityModel.Tokens -{ - /// - /// Contains the result of validating that a has not been replayed. - /// The contains a collection of for each step in the token validation. - /// - internal class ReplayValidationResult : ValidationResult - { - private Exception? _exception; - - /// - /// Creates an instance of . - /// - /// is the expiration date against which the token was validated. - public ReplayValidationResult(DateTime? expirationTime) : base(ValidationFailureType.ValidationSucceeded) - { - IsValid = true; - ExpirationTime = expirationTime; - } - - /// - /// Creates an instance of - /// - /// is the expiration date against which the token was validated. - /// is the that occurred during validation. - /// is the that occurred during validation. - public ReplayValidationResult(DateTime? expirationTime, ValidationFailureType validationFailure, ExceptionDetail exceptionDetail) - : base(validationFailure, exceptionDetail) - { - IsValid = false; - ExpirationTime = expirationTime; - } - - /// - /// Gets the that occurred during validation. - /// - public override Exception? Exception - { - get - { - if (_exception != null || ExceptionDetail == null) - return _exception; - - HasValidOrExceptionWasRead = true; - _exception = ExceptionDetail.GetException(); - _exception.Source = "Microsoft.IdentityModel.Tokens"; - - if (_exception is SecurityTokenReplayDetectedException securityTokenReplayDetectedException) - { - securityTokenReplayDetectedException.ExceptionDetail = ExceptionDetail; - } - else if (_exception is SecurityTokenReplayAddFailedException securityTokenReplayAddFailedException) - { - securityTokenReplayAddFailedException.ExceptionDetail = ExceptionDetail; - } - - return _exception; - } - } - - /// - /// Gets the expiration date against which the token was validated. - /// - public DateTime? ExpirationTime { get; } - } -} -#nullable restore diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/SignatureValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/SignatureValidationResult.cs deleted file mode 100644 index 7727a877a3..0000000000 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/SignatureValidationResult.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Threading; -using Microsoft.IdentityModel.Tokens; - -namespace Microsoft.IdentityModel.JsonWebTokens.Results -{ -#nullable enable - /// - /// Contains the result of validating a signature. - /// The contains a collection of for each step in the token validation. - /// - internal class SignatureValidationResult : ValidationResult - { - private Exception? _exception; - private static SignatureValidationResult? _successResult; - - /// - /// Creates an instance of representing the successful result of validating a signature. - /// - public SignatureValidationResult(bool isValid, ValidationFailureType validationFailureType) : base(validationFailureType) - { - IsValid = isValid; - } - - /// - /// Creates an instance of representing the failed result of validating a signature. - /// - /// is the that occurred while validating the signature. - /// contains the of the error that occurred while validating the signature. - public SignatureValidationResult(ValidationFailureType validationFailure, ExceptionDetail? exceptionDetail) - : base(validationFailure, exceptionDetail) - { - IsValid = false; - } - - /// - /// Creates an instance of representing a successful validation. - /// - internal static SignatureValidationResult Success() => - _successResult ?? - Interlocked.CompareExchange(ref _successResult, new SignatureValidationResult(true, ValidationFailureType.ValidationSucceeded), null) ?? - _successResult; - - /// - /// Creates an instance of representing a failure due to a null parameter. - /// - /// The name of the null parameter. - internal static SignatureValidationResult NullParameterFailure(string parameterName) => - new SignatureValidationResult( - ValidationFailureType.SignatureValidationFailed, - ExceptionDetail.NullParameter(parameterName)); - - /// - /// Gets the that occurred while validating the signature. - /// - public override Exception? Exception - { - get - { - if (_exception != null || ExceptionDetail == null) - return _exception; - - HasValidOrExceptionWasRead = true; - _exception = ExceptionDetail.GetException(); - _exception.Source = "Microsoft.IdentityModel.JsonWebTokens"; - - if (_exception is SecurityTokenException securityTokenException) - { - securityTokenException.ExceptionDetail = ExceptionDetail; - } - - return _exception; - } - } - } -#nullable restore -} diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/SigningKeyValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/SigningKeyValidationResult.cs deleted file mode 100644 index 6c3905c1cf..0000000000 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/SigningKeyValidationResult.cs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -#nullable enable -namespace Microsoft.IdentityModel.Tokens -{ - /// - /// Contains the result of validating the used to sign a . - /// The contains a collection of for each step in the token validation. - /// - internal class SigningKeyValidationResult : ValidationResult - { - private Exception? _exception; - - /// - /// Creates an instance of - /// - /// is the security key that was validated successfully. - public SigningKeyValidationResult(SecurityKey? signingKey) - : base(ValidationFailureType.ValidationSucceeded) - { - SigningKey = signingKey; - IsValid = true; - } - - /// - /// Creates an instance of - /// - /// is the security key that was intended to be validated. - /// is the that occurred during validation. - /// is the that occurred during validation. - public SigningKeyValidationResult(SecurityKey? signingKey, ValidationFailureType validationFailure, ExceptionDetail exceptionDetail) - : base(validationFailure, exceptionDetail) - { - SigningKey = signingKey; - IsValid = false; - } - - /// - /// Gets the that occurred during validation. - /// - public override Exception? Exception - { - get - { - if (_exception != null || ExceptionDetail == null) - return _exception; - - HasValidOrExceptionWasRead = true; - _exception = ExceptionDetail.GetException(); - if (_exception is SecurityTokenInvalidSigningKeyException securityTokenInvalidSigningKeyException) - { - securityTokenInvalidSigningKeyException.SigningKey = SigningKey; - securityTokenInvalidSigningKeyException.ExceptionDetail = ExceptionDetail; - securityTokenInvalidSigningKeyException.Source = "Microsoft.IdentityModel.Tokens"; - } - - return _exception; - } - } - - /// - /// Gets the security key that was validated or intended to be validated. - /// - public SecurityKey? SigningKey { get; } - } -} -#nullable restore diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenDecryptionResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenDecryptionResult.cs deleted file mode 100644 index 99488e75ba..0000000000 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenDecryptionResult.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; - -#nullable enable -namespace Microsoft.IdentityModel.Tokens -{ - /// - /// Contains the result of decrypting a securityToken in clear text. - /// The contains a collection of for each step in the token validation. - /// - internal class TokenDecryptionResult : ValidationResult - { - private Exception? _exception; - private string? _decryptedToken; - - /// - /// Creates an instance of containing the clear text result of decrypting a security token. - /// - /// The clear text result of decrypting the security token. - /// The SecurityToken that contains the cypher text. - public TokenDecryptionResult(string decryptedToken, SecurityToken securityToken) - : base(ValidationFailureType.ValidationSucceeded) - { - IsValid = true; - _decryptedToken = decryptedToken; - SecurityToken = securityToken; - } - - /// - /// Creates an instance of - /// - /// is the securityToken that could not be decrypted. - /// is the that occurred during reading. - /// is the that occurred during reading. - public TokenDecryptionResult(SecurityToken? securityToken, ValidationFailureType validationFailure, ExceptionDetail exceptionDetail) - : base(validationFailure, exceptionDetail) - { - SecurityToken = securityToken; - IsValid = false; - } - - /// - /// Creates an instance of representing a failure due to a null parameter. - /// - /// The securityToken that could not be decrypted. - /// The name of the null parameter. - internal static TokenDecryptionResult NullParameterFailure(SecurityToken? securityToken, string parameterName) => - new TokenDecryptionResult( - securityToken, - ValidationFailureType.TokenDecryptionFailed, - ExceptionDetail.NullParameter(parameterName)); - - /// - /// Gets the decoded contents of the SecurityToken. - /// - /// if the result is not valid, and the decrypted token is not available. - /// It is expected that this method will only be called if returns true. - public string DecryptedToken() - { - if (_decryptedToken is null) - throw new InvalidOperationException("Attempted to retrieve the DecryptedToken from a failed TokenDecrypting result."); - - return _decryptedToken; - } - - /// - /// Gets the that occurred during reading. - /// - public override Exception? Exception - { - get - { - if (_exception != null || ExceptionDetail == null) - return _exception; - - HasValidOrExceptionWasRead = true; - _exception = ExceptionDetail.GetException(); - - if (_exception is SecurityTokenException securityTokenException) - { - securityTokenException.Source = "Microsoft.IdentityModel.Tokens"; - securityTokenException.ExceptionDetail = ExceptionDetail; - } - - return _exception; - } - } - - /// - /// The on which decryption was attempted. - /// - public SecurityToken? SecurityToken { get; } - } -} -#nullable restore diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenReadingResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenReadingResult.cs deleted file mode 100644 index 38002bd071..0000000000 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenReadingResult.cs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; - -#nullable enable -namespace Microsoft.IdentityModel.Tokens -{ - /// - /// Contains the result of reading a . - /// The contains a collection of for each step in the token validation. - /// - internal class TokenReadingResult : ValidationResult - { - private Exception? _exception; - private SecurityToken? _securityToken; - - /// - /// Creates an instance of . - /// - /// is the string from which the was created. - /// is the that was created. - public TokenReadingResult(SecurityToken securityToken, string tokenInput) - : base(ValidationFailureType.ValidationSucceeded) - { - IsValid = true; - TokenInput = tokenInput; - _securityToken = securityToken; - } - - /// - /// Creates an instance of - /// - /// is the string that failed to create a . - /// is the that occurred during reading. - /// is the that occurred during reading. - public TokenReadingResult(string? tokenInput, ValidationFailureType validationFailure, ExceptionDetail exceptionDetail) - : base(validationFailure, exceptionDetail) - { - TokenInput = tokenInput; - IsValid = false; - } - - /// - /// Gets the that was read. - /// - /// if the is null. - /// It is expected that the caller would check returns true before accessing this. - public SecurityToken SecurityToken() - { - if (_securityToken is null) - throw new InvalidOperationException("Attempted to retrieve the SecurityToken from a failed TokenReading result."); - - return _securityToken; - } - - /// - /// Gets the that occurred during reading. - /// - public override Exception? Exception - { - get - { - if (_exception != null || ExceptionDetail == null) - return _exception; - - HasValidOrExceptionWasRead = true; - _exception = ExceptionDetail.GetException(); - - if (_exception is SecurityTokenException securityTokenException) - { - securityTokenException.Source = "Microsoft.IdentityModel.Tokens"; - securityTokenException.ExceptionDetail = ExceptionDetail; - } - - return _exception; - } - } - - /// - /// Gets the string from which the was read. - /// - public string? TokenInput { get; } - } -} -#nullable restore diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenTypeValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenTypeValidationResult.cs deleted file mode 100644 index e098694e71..0000000000 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenTypeValidationResult.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -#nullable enable -namespace Microsoft.IdentityModel.Tokens -{ - /// - /// Contains the result of validating the TokenType of a . - /// The contains a collection of for each step in the token validation. - /// - internal class TokenTypeValidationResult : ValidationResult - { - private Exception? _exception; - private const string TokenSource = "Microsoft.IdentityModel.Tokens"; - - /// - /// Creates an instance of . - /// - /// is the type against which the token was validated. - public TokenTypeValidationResult(string? type) - : base(ValidationFailureType.ValidationSucceeded) - { - Type = type; - IsValid = true; - } - - /// - /// Creates an instance of - /// - /// is the type against which the token was validated. - /// is the that occurred during validation. - /// is the that occurred during validation. - public TokenTypeValidationResult(string? type, ValidationFailureType validationFailure, ExceptionDetail exceptionDetail) - : base(validationFailure, exceptionDetail) - { - Type = type; - IsValid = false; - } - - /// - /// Gets the that occurred during validation. - /// - public override Exception? Exception - { - get - { - if (_exception != null || ExceptionDetail == null) - return _exception; - - HasValidOrExceptionWasRead = true; - _exception = ExceptionDetail.GetException(); - if (_exception is SecurityTokenInvalidTypeException securityTokenInvalidTypeException) - { - securityTokenInvalidTypeException.InvalidType = Type; - securityTokenInvalidTypeException.Source = TokenSource; - } - - return _exception; - } - } - - /// - /// Gets the security token type. - /// - public string? Type { get; } - - } -} -#nullable restore diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs index 7c37817080..6abeaa2e31 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs @@ -3,19 +3,47 @@ #nullable enable +using System; + namespace Microsoft.IdentityModel.Tokens { + internal interface ITokenValidationError + { + ValidationErrorType ErrorType { get; } + MessageDetail MessageDetail { get; } + int Tag { get; } + + Exception? InnerException { get; } + } + internal record struct TokenValidationError( ValidationErrorType ErrorType, MessageDetail MessageDetail, - int Tag) + int Tag, + Exception? InnerException) : ITokenValidationError + { + } + + /// + /// + /// + public static class TokenValidationErrorCommon { + /// + /// + /// + /// + /// + /// + internal static TokenValidationError NullParameter(string parameterName, int tag) + => new(ValidationErrorType.ArgumentNull, MessageDetail.NullParameter(parameterName), tag, null); } internal enum ValidationErrorType { Unknown = -1, ArgumentNull, + InvalidArgument, InvalidOperation, SecurityToken, SecurityTokenDecompressionFailed, diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationResult.cs index 9e435baea5..ebd1190a29 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationResult.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationResult.cs @@ -37,6 +37,7 @@ public class TokenValidationResult // TODO - lazy creation of _validationResults private List _validationResults; + private ITokenValidationError _tokenValidationError; private Exception _exception; private bool _isValid; @@ -78,31 +79,39 @@ internal TokenValidationResult( /// /// /// + /// /// This constructor is used by JsonWebTokenHandler as part of delaying creation of ClaimsIdentity. internal TokenValidationResult( SecurityToken securityToken, TokenHandler tokenHandler, ValidationParameters validationParameters, string issuer, - List validationResults) + List validationResults, + ITokenValidationError tokenValidationError) { _validationParameters = validationParameters; _tokenHandler = tokenHandler; _validationResults = validationResults; Issuer = issuer; SecurityToken = securityToken; + _tokenValidationError = tokenValidationError; } /// - /// Adds a to the list of . + /// Initializes a new instance of using . /// - /// the associated with one of the validation steps. For example . - internal void AddValidationResult(ValidationResult validationResult) + /// + /// + /// + /// This constructor is used by JsonWebTokenHandler as part of delaying creation of ClaimsIdentity. + internal TokenValidationResult( + TokenHandler tokenHandler, + ValidationParameters validationParameters, + ITokenValidationError tokenValidationError) { - if (validationResult is null) - throw LogHelper.LogArgumentNullException(nameof(validationResult)); - - _validationResults.Add(validationResult); + _tokenHandler = tokenHandler; + _tokenValidationError = tokenValidationError; + _validationParameters = validationParameters; } /// @@ -211,11 +220,11 @@ public Exception Exception get { HasValidOrExceptionWasRead = true; - if (_exception is null) - { - if (ExceptionDetail is not null) - return ExceptionDetail.GetException(); - } + if (_exception is null && _tokenValidationError is not null) + return ExceptionDetail.ExceptionFromType( + _tokenValidationError.ErrorType, + _tokenValidationError.MessageDetail, + null); return _exception; } @@ -225,28 +234,6 @@ public Exception Exception } } - /// - /// Gets the for the first failed validation result. - /// - private ExceptionDetail ExceptionDetail - { - get - { - if (ValidationResults.Count == 0) - return null; - - // Iterate in reverse since the failure should be the last result - for (int i = ValidationResults.Count - 1; i >= 0; i--) - { - ValidationResult validationResult = ValidationResults[i]; - if (validationResult.ExceptionDetail != null) - return validationResult.ExceptionDetail; - } - - return null; - } - } - internal bool HasValidOrExceptionWasRead { get; set; } /// @@ -306,19 +293,5 @@ public bool IsValid /// (e.g for a JSON Web Token, from the "typ" header). /// public string TokenType { get; set; } - - /// - /// Gets the list of that contains the result of validating the token. - /// - internal IReadOnlyList ValidationResults - { - get - { - if (_validationResults is null) - Interlocked.CompareExchange(ref _validationResults, new List(), null); - - return _validationResults.AsReadOnly(); - } - } } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs index dd62bb549d..83fff576e0 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs @@ -1,89 +1,53 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +#nullable enable using System; -using System.Collections.Generic; -using System.Diagnostics; -#nullable enable namespace Microsoft.IdentityModel.Tokens { /// /// Contains results of a single step in validating a . /// A maintains a list of for each step in the token validation. /// - internal abstract class ValidationResult + internal class ValidationResult { - private bool _isValid; - - /// - /// Creates an instance of - /// - protected ValidationResult() - { - ValidationFailureType = ValidationFailureType.ValidationNotEvaluated; - } - /// /// Creates an instance of /// - /// The that occurred during validation. - protected ValidationResult(ValidationFailureType validationFailureType) + /// The that is being validated. + /// The that is being used to validate the token. + /// The to be used for validating the token. + internal ValidationResult( + SecurityToken securityToken, + TokenHandler tokenHandler, + ValidationParameters validationParameters) { - ValidationFailureType = validationFailureType; + TokenHandler = tokenHandler ?? throw new ArgumentNullException("TokenHandler cannot be null."); + SecurityToken = securityToken; + ValidationParameters = validationParameters; + IsValid = true; } - /// - /// Creates an instance of - /// - /// The that occurred during validation. - /// The representing the that occurred during validation. - protected ValidationResult(ValidationFailureType validationFailureType, ExceptionDetail? exceptionDetail) + public ValidationResult( + SecurityToken? securityToken, + TokenHandler tokenHandler, + ValidationParameters? validationParameters, + ITokenValidationError tokenValidationError) { - ValidationFailureType = validationFailureType; - ExceptionDetail = exceptionDetail; + TokenHandler = tokenHandler ?? throw new ArgumentNullException("TokenHandler cannot be null."); + SecurityToken = securityToken; + ValidationParameters = validationParameters; + TokenValidationError = tokenValidationError; + IsValid = false; } - /// - /// Adds a new stack frame to the exception details. - /// - /// - public void AddStackFrame(StackFrame stackFrame) - { - ExceptionDetail?.StackFrames.Add(stackFrame); - } - - /// - /// Gets the that occurred during validation. - /// - public abstract Exception? Exception { get; } - - /// - /// Gets the that occurred during validation. - /// - public ExceptionDetail? ExceptionDetail { get; } - /// /// True if the token was successfully validated, false otherwise. /// - public bool IsValid - { - get - { - HasValidOrExceptionWasRead = true; - return _isValid; - } - set - { - _isValid = value; - } - } + public bool IsValid { get; private set; } - // TODO - HasValidOrExceptionWasRead, IsValid, Exception are temporary and will be removed when TokenValidationResult derives from ValidationResult. - /// - /// Gets or sets a boolean recording if IsValid or Exception was called. - /// - protected bool HasValidOrExceptionWasRead { get; set; } + public ITokenValidationError? TokenValidationError { get; private set; } /// /// Logs the validation result. @@ -95,18 +59,23 @@ public void Log() // TODO - Do we need this, how will it work? } - /// - /// Contains any logs that would have been written. - /// - public IList LogDetails { get; } = new List(); + public SecurityToken? SecurityToken { get; private set; } + + public TokenHandler TokenHandler { get; private set; } + + public ValidationParameters? ValidationParameters { get; private set; } + + #region Validation Results + public ValidationResult? ActorValidationResult { get; internal set; } + public string? ValidatedAudience { get; internal set; } + public ValidatedIssuer ValidatedIssuer { get; internal set; } + public ValidatedLifetime? ValidatedLifetime { get; internal set; } + public DateTime? ValidatedTokenReplayExpirationTime { get; internal set; } + public ValidatedTokenType? ValidatedTokenType { get; internal set; } + public SecurityKey? ValidatedSigningKey { get; internal set; } + public ValidatedSigningKeyLifetime? ValidatedSigningKeyLifetime { get; internal set; } + #endregion - /// - /// Gets the indicating why the validation was not satisfied. - /// - public ValidationFailureType ValidationFailureType - { - get; - } = ValidationFailureType.ValidationNotEvaluated; } } #nullable disable diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs b/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs index fd0be8a668..f278fe7fe6 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs @@ -6,7 +6,7 @@ using System.ComponentModel; using System.Security.Claims; using System.Threading; -//using Microsoft.IdentityModel.Abstractions; +using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; namespace Microsoft.IdentityModel.Tokens @@ -493,7 +493,7 @@ public TokenReplayValidatorDelegate TokenReplayValidator /// /// Allows overriding the delegate that will be used to validate the type of the token. - /// If the token type cannot be validated, a MUST be returned by the delegate. + /// If the token type cannot be validated, a MUST be returned by the delegate. /// Note: the 'type' parameter may be null if it couldn't be extracted from its usual location. /// Implementations that need to resolve it from a different location can use the 'token' parameter. /// diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs index f2e024def6..05fd244453 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; #nullable enable @@ -16,9 +17,9 @@ namespace Microsoft.IdentityModel.Tokens /// The being validated. /// required for validation. /// - /// A that contains the results of validating the algorithm. + /// A that contains the results of validating the algorithm. /// This delegate is not expected to throw. - internal delegate AlgorithmValidationResult AlgorithmValidatorDelegate( + internal delegate Result AlgorithmValidatorDelegate( string algorithm, SecurityKey securityKey, SecurityToken securityToken, @@ -36,7 +37,7 @@ public static partial class Validators /// required for validation. /// #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging - internal static AlgorithmValidationResult ValidateAlgorithm( + internal static Result ValidateAlgorithm( string algorithm, SecurityKey securityKey, SecurityToken securityToken, @@ -45,30 +46,18 @@ internal static AlgorithmValidationResult ValidateAlgorithm( #pragma warning restore CA1801 // TODO: remove pragma disable once callContext is used for logging { if (validationParameters == null) - { - return new AlgorithmValidationResult( - algorithm, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII(nameof(validationParameters))), - ValidationErrorType.ArgumentNull)); - } + return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123123)); if (validationParameters.ValidAlgorithms != null && validationParameters.ValidAlgorithms.Count > 0 && !validationParameters.ValidAlgorithms.Contains(algorithm, StringComparer.Ordinal)) - { - return new AlgorithmValidationResult( - algorithm, - ValidationFailureType.AlgorithmValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10696, - LogHelper.MarkAsNonPII(algorithm)), - ValidationErrorType.SecurityTokenInvalidAlgorithm)); - } + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAlgorithm, + new MessageDetail( + LogMessages.IDX10696, + LogHelper.MarkAsNonPII(algorithm)), + 0x123123, + null)); - return new AlgorithmValidationResult(algorithm); + return new(algorithm); } } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs index 717aaa9cd9..71cc2e1c2e 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs @@ -16,9 +16,9 @@ namespace Microsoft.IdentityModel.Tokens /// The that is being validated. /// The to be used for validating the token. /// - /// A that contains the results of validating the issuer. + /// A that contains the results of validating the issuer. /// This delegate is not expected to throw. - internal delegate AudienceValidationResult AudienceValidatorDelegate( + internal delegate Result AudienceValidatorDelegate( IList audiences, SecurityToken? securityToken, ValidationParameters validationParameters, @@ -42,52 +42,34 @@ public static partial class Validators /// If none of the 'audiences' matched either or one of . /// An EXACT match is required. #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging - internal static AudienceValidationResult ValidateAudience(IList tokenAudiences, SecurityToken? securityToken, ValidationParameters validationParameters, CallContext callContext) + internal static Result ValidateAudience(IList tokenAudiences, SecurityToken? securityToken, ValidationParameters validationParameters, CallContext callContext) #pragma warning restore CA1801 { if (validationParameters == null) - return new AudienceValidationResult( - Utility.SerializeAsSingleCommaDelimitedString(tokenAudiences), - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII(nameof(validationParameters))), - ValidationErrorType.ArgumentNull)); + return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123123)); if (tokenAudiences == null) - return new AudienceValidationResult( - Utility.SerializeAsSingleCommaDelimitedString(tokenAudiences), - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10207, - null), - ValidationErrorType.SecurityTokenInvalidAudience)); + return new(TokenValidationErrorCommon.NullParameter(nameof(tokenAudiences), 0x123123)); if (tokenAudiences.Count == 0) - return new AudienceValidationResult( - Utility.SerializeAsSingleCommaDelimitedString(tokenAudiences), - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10206, - null), - ValidationErrorType.SecurityTokenInvalidAudience)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail(LogMessages.IDX10206), + 0x123123, + null)); string? validAudience = ValidTokenAudience(tokenAudiences, validationParameters.ValidAudiences, validationParameters.IgnoreTrailingSlashWhenValidatingAudience); if (validAudience != null) - return new AudienceValidationResult(validAudience); - - return new AudienceValidationResult( - Utility.SerializeAsSingleCommaDelimitedString(tokenAudiences), - ValidationFailureType.AudienceValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10215, - LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(tokenAudiences)), - LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidAudiences))), - ValidationErrorType.SecurityTokenInvalidAudience)); + return new(validAudience); + + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10215, + LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(tokenAudiences)), + LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidAudiences))), + 0x123123, + null)); } private static string? ValidTokenAudience(IList tokenAudiences, IList validAudiences, bool ignoreTrailingSlashWhenValidatingAudience) diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs index 8c9cc9a972..1036c613eb 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs @@ -3,12 +3,24 @@ using System.Threading; using System.Threading.Tasks; +using Microsoft.IdentityModel.Abstractions; + //using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; namespace Microsoft.IdentityModel.Tokens { #nullable enable + internal enum IssuerValidationSource + { + NotValidated = 0, + IssuerIsConfigurationIssuer, + IssuerIsValidIssuer, + IssuerIsAmongValidIssuers + } + + internal record struct ValidatedIssuer(string Issuer, IssuerValidationSource ValidationSource); + /// /// Definition for delegate that will validate the issuer value in a token. /// @@ -17,9 +29,9 @@ namespace Microsoft.IdentityModel.Tokens /// The to be used for validating the token. /// /// - /// An that contains the results of validating the issuer. + /// An that contains the results of validating the issuer. /// This delegate is not expected to throw. - internal delegate Task IssuerValidationDelegateAsync( + internal delegate Task> IssuerValidationDelegateAsync( string issuer, SecurityToken securityToken, ValidationParameters validationParameters, @@ -39,9 +51,9 @@ public static partial class Validators /// The to be used for validating the token. /// /// - /// An that contains the results of validating the issuer. + /// An that contains either the issuer that was validated or an error. /// An EXACT match is required. - internal static async Task ValidateIssuerAsync( + internal static async Task> ValidateIssuerAsync( string issuer, SecurityToken securityToken, ValidationParameters validationParameters, @@ -51,39 +63,17 @@ internal static async Task ValidateIssuerAsync( CancellationToken? cancellationToken) { if (string.IsNullOrWhiteSpace(issuer)) - { - return new IssuerValidationResult( - issuer, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10211, - null), - ValidationErrorType.SecurityTokenInvalidIssuer, - null)); - } + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidIssuer, + new MessageDetail(LogMessages.IDX10211), + 0x123123, + null)); if (validationParameters == null) - return new IssuerValidationResult( - issuer, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII(nameof(validationParameters))), - ValidationErrorType.ArgumentNull, - null)); + return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123123)); if (securityToken == null) - return new IssuerValidationResult( - issuer, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII(nameof(securityToken))), - ValidationErrorType.ArgumentNull, - null)); + return new(TokenValidationErrorCommon.NullParameter(nameof(securityToken), 0x123123)); BaseConfiguration? configuration = null; if (validationParameters.ConfigurationManager != null) @@ -91,16 +81,11 @@ internal static async Task ValidateIssuerAsync( // Return failed IssuerValidationResult if all possible places to validate against are null or empty. if (validationParameters.ValidIssuers.Count == 0 && string.IsNullOrWhiteSpace(configuration?.Issuer)) - { - return new IssuerValidationResult( - issuer, - ValidationFailureType.IssuerValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10211, - null), - ValidationErrorType.SecurityTokenInvalidIssuer)); - } + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidIssuer, + new MessageDetail(LogMessages.IDX10211), + 0x123123, + null)); if (configuration != null) { @@ -113,8 +98,8 @@ internal static async Task ValidateIssuerAsync( //if (LogHelper.IsEnabled(EventLogLevel.Informational)) // LogHelper.LogInformation(LogMessages.IDX10236, LogHelper.MarkAsNonPII(issuer), callContext); - return new IssuerValidationResult(issuer, - IssuerValidationResult.ValidationSource.IssuerIsConfigurationIssuer); + + return new(new ValidatedIssuer(issuer, IssuerValidationSource.IssuerIsConfigurationIssuer)); } } @@ -137,22 +122,20 @@ internal static async Task ValidateIssuerAsync( //if (LogHelper.IsEnabled(EventLogLevel.Informational)) // LogHelper.LogInformation(LogMessages.IDX10236, LogHelper.MarkAsNonPII(issuer)); - return new IssuerValidationResult(issuer, - IssuerValidationResult.ValidationSource.IssuerIsAmongValidIssuers); + return new(new ValidatedIssuer(issuer, IssuerValidationSource.IssuerIsAmongValidIssuers)); } } } - return new IssuerValidationResult( - issuer, - ValidationFailureType.IssuerValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10212, - LogHelper.MarkAsNonPII(issuer), - LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidIssuers)), - LogHelper.MarkAsNonPII(configuration?.Issuer)), - ValidationErrorType.SecurityTokenInvalidIssuer)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidIssuer, + new MessageDetail( + LogMessages.IDX10212, + LogHelper.MarkAsNonPII(issuer), + LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidIssuers)), + LogHelper.MarkAsNonPII(configuration?.Issuer)), + 0x123123, + null)); } } #nullable restore diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs index 4ba55d2fe7..b707bc2fa2 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs @@ -3,12 +3,16 @@ using System; using System.Security.Cryptography.X509Certificates; +using Microsoft.IdentityModel.Abstractions; + //using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; #nullable enable namespace Microsoft.IdentityModel.Tokens { + internal record struct ValidatedSigningKeyLifetime(DateTime? ValidFrom, DateTime? ValidTo, DateTime? ValidationTime); + /// /// Definition for delegate that will validate the that signed a . /// @@ -17,9 +21,9 @@ namespace Microsoft.IdentityModel.Tokens /// The to be used for validating the token. /// The to be used for validation. /// The to be used for logging. - /// A that contains the results of validating the issuer. + /// A that contains the results of validating the issuer. /// This delegate is not expected to throw. - internal delegate SigningKeyValidationResult IssuerSigningKeyValidatorDelegate( + internal delegate Result IssuerSigningKeyValidatorDelegate( SecurityKey signingKey, SecurityToken securityToken, ValidationParameters validationParameters, @@ -43,7 +47,7 @@ public static partial class Validators /// if 'securityKey' is null and ValidateIssuerSigningKey is true. /// if 'securityToken' is null and ValidateIssuerSigningKey is true. /// if 'validationParameters' is null. - internal static SigningKeyValidationResult ValidateIssuerSigningKey( + internal static Result ValidateIssuerSigningKey( SecurityKey securityKey, SecurityToken securityToken, ValidationParameters validationParameters, @@ -53,36 +57,19 @@ internal static SigningKeyValidationResult ValidateIssuerSigningKey( CallContext? callContext) { if (validationParameters == null) - return new SigningKeyValidationResult( - securityKey, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII(nameof(validationParameters))), - ValidationErrorType.ArgumentNull)); + return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123123)); if (securityKey == null) - { - return new SigningKeyValidationResult( - securityKey, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10253, - LogHelper.MarkAsNonPII(nameof(securityKey))), - ValidationErrorType.ArgumentNull)); - } + return new(new TokenValidationError( + ValidationErrorType.ArgumentNull, + new MessageDetail( + LogMessages.IDX10253, + nameof(securityKey)), + 0x123123, + null)); if (securityToken == null) - return new SigningKeyValidationResult( - securityKey, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII(nameof(securityToken))), - ValidationErrorType.ArgumentNull)); + return new(TokenValidationErrorCommon.NullParameter(nameof(securityToken), 0x123123)); return ValidateIssuerSigningKeyLifeTime(securityKey, validationParameters, callContext); } @@ -94,53 +81,52 @@ internal static SigningKeyValidationResult ValidateIssuerSigningKey( /// The to be used for validating the token. /// #pragma warning disable CA1801 // Review unused parameters - internal static SigningKeyValidationResult ValidateIssuerSigningKeyLifeTime( + internal static Result ValidateIssuerSigningKeyLifeTime( SecurityKey securityKey, ValidationParameters validationParameters, CallContext? callContext) #pragma warning restore CA1801 // Review unused parameters { + DateTime utcNow = DateTime.UtcNow; + DateTime? notBeforeUtc = null; + DateTime? notAfterUtc = null; X509SecurityKey? x509SecurityKey = securityKey as X509SecurityKey; + if (x509SecurityKey?.Certificate is X509Certificate2 cert) { - DateTime utcNow = DateTime.UtcNow; - var notBeforeUtc = cert.NotBefore.ToUniversalTime(); - var notAfterUtc = cert.NotAfter.ToUniversalTime(); + notBeforeUtc = cert.NotBefore.ToUniversalTime(); + notAfterUtc = cert.NotAfter.ToUniversalTime(); if (notBeforeUtc > DateTimeUtil.Add(utcNow, validationParameters.ClockSkew)) - return new SigningKeyValidationResult( - securityKey, - ValidationFailureType.SigningKeyValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogHelper.FormatInvariant( - LogMessages.IDX10248, - LogHelper.MarkAsNonPII(notBeforeUtc), - LogHelper.MarkAsNonPII(utcNow))), - ValidationErrorType.SecurityTokenInvalidSigningKey)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidSigningKey, + new MessageDetail( + LogMessages.IDX10248, + LogHelper.MarkAsNonPII(notBeforeUtc), + LogHelper.MarkAsNonPII(utcNow)), + 0x123123, + null)); //TODO: Move to CallContext //if (LogHelper.IsEnabled(EventLogLevel.Informational)) // LogHelper.LogInformation(LogMessages.IDX10250, LogHelper.MarkAsNonPII(notBeforeUtc), LogHelper.MarkAsNonPII(utcNow)); if (notAfterUtc < DateTimeUtil.Add(utcNow, validationParameters.ClockSkew.Negate())) - return new SigningKeyValidationResult( - securityKey, - ValidationFailureType.SigningKeyValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogHelper.FormatInvariant( - LogMessages.IDX10249, - LogHelper.MarkAsNonPII(notAfterUtc), - LogHelper.MarkAsNonPII(utcNow))), - ValidationErrorType.SecurityTokenInvalidSigningKey)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidSigningKey, + new MessageDetail( + LogMessages.IDX10249, + LogHelper.MarkAsNonPII(notAfterUtc), + LogHelper.MarkAsNonPII(utcNow)), + 0x123123, + null)); // TODO: Move to CallContext //if (LogHelper.IsEnabled(EventLogLevel.Informational)) // LogHelper.LogInformation(LogMessages.IDX10251, LogHelper.MarkAsNonPII(notAfterUtc), LogHelper.MarkAsNonPII(utcNow)); } - return new SigningKeyValidationResult(securityKey); + return new(new ValidatedSigningKeyLifetime(notBeforeUtc, notAfterUtc, utcNow)); } } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs index 00148636a0..3d9dfafdd3 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs @@ -8,6 +8,8 @@ #nullable enable namespace Microsoft.IdentityModel.Tokens { + internal record struct ValidatedLifetime(DateTime? NotBefore, DateTime? Expires); + /// /// Definition for delegate that will validate the lifetime of a . /// @@ -16,9 +18,9 @@ namespace Microsoft.IdentityModel.Tokens /// The that is being validated. /// The to be used for validating the token. /// - /// A that contains the results of validating the issuer. + /// A that contains the results of validating the issuer. /// This delegate is not expected to throw. - internal delegate LifetimeValidationResult LifetimeValidatorDelegate( + internal delegate Result LifetimeValidatorDelegate( DateTime? notBefore, DateTime? expires, SecurityToken? securityToken, @@ -38,82 +40,70 @@ public static partial class Validators /// The being validated. /// The to be used for validating the token. /// - /// A indicating whether validation was successful, and providing a if it was not. + /// A indicating whether validation was successful, and providing a if it was not. /// If 'validationParameters' is null. /// If 'expires.HasValue' is false. /// If 'notBefore' is > 'expires'. /// If 'notBefore' is > DateTime.UtcNow. /// If 'expires' is < DateTime.UtcNow. /// All time comparisons apply . - /// Exceptions are not thrown, but embedded in . #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging - internal static LifetimeValidationResult ValidateLifetime(DateTime? notBefore, DateTime? expires, SecurityToken? securityToken, ValidationParameters validationParameters, CallContext callContext) + internal static Result ValidateLifetime( + DateTime? notBefore, + DateTime? expires, + SecurityToken? securityToken, + ValidationParameters validationParameters, + CallContext callContext) #pragma warning restore CA1801 { if (validationParameters == null) - return new LifetimeValidationResult( - notBefore, - expires, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII(nameof(validationParameters))), - ValidationErrorType.ArgumentNull)); + return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123123)); if (!expires.HasValue) - return new LifetimeValidationResult( - notBefore, - expires, - ValidationFailureType.LifetimeValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10225, - LogHelper.MarkAsNonPII(securityToken == null ? "null" : securityToken.GetType().ToString())), - ValidationErrorType.SecurityTokenNoExpiration)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenNoExpiration, + new MessageDetail( + LogMessages.IDX10225, + LogHelper.MarkAsNonPII(securityToken == null ? "null" : securityToken.GetType().ToString())), + 0x123123, + null)); if (notBefore.HasValue && expires.HasValue && (notBefore.Value > expires.Value)) - return new LifetimeValidationResult( - notBefore, - expires, - ValidationFailureType.LifetimeValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10224, - LogHelper.MarkAsNonPII(notBefore.Value), - LogHelper.MarkAsNonPII(expires.Value)), - ValidationErrorType.SecurityTokenInvalidLifetime)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidLifetime, + new MessageDetail( + LogMessages.IDX10224, + LogHelper.MarkAsNonPII(notBefore.Value), + LogHelper.MarkAsNonPII(expires.Value)), + 0x123123, + null)); DateTime utcNow = DateTime.UtcNow; if (notBefore.HasValue && (notBefore.Value > DateTimeUtil.Add(utcNow, validationParameters.ClockSkew))) - return new LifetimeValidationResult( - notBefore, - expires, - ValidationFailureType.LifetimeValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10222, - LogHelper.MarkAsNonPII(notBefore.Value), - LogHelper.MarkAsNonPII(utcNow)), - ValidationErrorType.SecurityTokenNotYetValid)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenNotYetValid, + new MessageDetail( + LogMessages.IDX10222, + LogHelper.MarkAsNonPII(notBefore.Value), + LogHelper.MarkAsNonPII(utcNow)), + 0x123123, + null)); if (expires.HasValue && (expires.Value < DateTimeUtil.Add(utcNow, validationParameters.ClockSkew.Negate()))) - return new LifetimeValidationResult( - notBefore, - expires, - ValidationFailureType.LifetimeValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10223, - LogHelper.MarkAsNonPII(expires.Value), - LogHelper.MarkAsNonPII(utcNow)), - ValidationErrorType.SecurityTokenExpired)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenExpired, + new MessageDetail( + LogMessages.IDX10223, + LogHelper.MarkAsNonPII(expires.Value), + LogHelper.MarkAsNonPII(utcNow)), + 0x123123, + null)); // if it reaches here, that means lifetime of the token is valid if (LogHelper.IsEnabled(EventLogLevel.Informational)) LogHelper.LogInformation(LogMessages.IDX10239); - return new LifetimeValidationResult(notBefore, expires); + return new(new ValidatedLifetime(notBefore, expires)); } } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs index 6f189a8567..522065685f 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; namespace Microsoft.IdentityModel.Tokens @@ -13,9 +14,9 @@ namespace Microsoft.IdentityModel.Tokens /// The security token that is being validated. /// The to be used for validating the token. /// - /// A that contains the results of validating the token. + /// A that contains the results of validating the token. /// This delegate is not expected to throw. - internal delegate ReplayValidationResult TokenReplayValidatorDelegate( + internal delegate Result TokenReplayValidatorDelegate( DateTime? expirationTime, string securityToken, ValidationParameters validationParameters, @@ -39,72 +40,50 @@ public static partial class Validators /// If the 'securityToken' is found in the cache. /// If the 'securityToken' could not be added to the . #pragma warning disable CA1801 // Review unused parameters - internal static ReplayValidationResult ValidateTokenReplay(DateTime? expirationTime, string securityToken, ValidationParameters validationParameters, CallContext callContext) + internal static Result ValidateTokenReplay(DateTime? expirationTime, string securityToken, ValidationParameters validationParameters, CallContext callContext) #pragma warning restore CA1801 // Review unused parameters { if (string.IsNullOrWhiteSpace(securityToken)) - return new ReplayValidationResult( - expirationTime, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII(nameof(securityToken))), - ValidationErrorType.ArgumentNull, - null)); + return new(TokenValidationErrorCommon.NullParameter(nameof(securityToken), 0x123123)); if (validationParameters == null) - return new ReplayValidationResult( - expirationTime, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII(nameof(validationParameters))), - ValidationErrorType.ArgumentNull, - null)); + return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123123)); // check if token if replay cache is set, then there must be an expiration time. if (validationParameters.TokenReplayCache != null) { if (expirationTime == null) - return new ReplayValidationResult( - expirationTime, - ValidationFailureType.TokenReplayValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10227, - LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), - ValidationErrorType.SecurityTokenReplayDetected, - null)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenReplayDetected, + new MessageDetail( + LogMessages.IDX10227, + LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), + 0x123123, + null)); if (validationParameters.TokenReplayCache.TryFind(securityToken)) - return new ReplayValidationResult( - expirationTime, - ValidationFailureType.TokenReplayValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10228, - LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), - ValidationErrorType.SecurityTokenReplayDetected, - null)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenReplayDetected, + new MessageDetail( + LogMessages.IDX10228, + LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), + 0x123123, + null)); if (!validationParameters.TokenReplayCache.TryAdd(securityToken, expirationTime.Value)) - return new ReplayValidationResult( - expirationTime, - ValidationFailureType.TokenReplayValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10229, - LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), - ValidationErrorType.SecurityTokenReplayAddFailed, - null)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenReplayAddFailed, + new MessageDetail( + LogMessages.IDX10229, + LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), + 0x123123, + null)); } // if it reaches here, that means no token replay is detected. // TODO: Move to CallContext //LogHelper.LogInformation(LogMessages.IDX10240); - return new ReplayValidationResult(expirationTime); + return new(expirationTime); } } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs index 855b09a7c8..676e1a361a 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs @@ -3,12 +3,15 @@ using System; using System.Linq; +using Microsoft.IdentityModel.Abstractions; + //using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; #nullable enable namespace Microsoft.IdentityModel.Tokens { + internal record struct ValidatedTokenType(string Type, int ValidTypeCount); /// /// Definition for delegate that will validate the token type of a token. /// @@ -16,9 +19,9 @@ namespace Microsoft.IdentityModel.Tokens /// The that is being validated. /// required for validation. /// - /// A that contains the results of validating the token type. + /// A that contains the results of validating the token type. /// An EXACT match is required. (case sensitive) is used for comparing against . - internal delegate TokenTypeValidationResult TypeValidatorDelegate( + internal delegate Result TypeValidatorDelegate( string? type, SecurityToken? securityToken, ValidationParameters validationParameters, @@ -33,10 +36,10 @@ public static partial class Validators /// The that is being validated. /// required for validation. /// - /// A that contains the results of validating the token type. + /// A that contains the results of validating the token type. /// An EXACT match is required. (case sensitive) is used for comparing against . #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging - internal static TokenTypeValidationResult ValidateTokenType( + internal static Result ValidateTokenType( string? type, SecurityToken? securityToken, ValidationParameters validationParameters, @@ -44,65 +47,41 @@ internal static TokenTypeValidationResult ValidateTokenType( #pragma warning restore CA1801 // TODO: remove pragma disable once callContext is used for logging { if (securityToken == null) - { - return new TokenTypeValidationResult( - type, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII(nameof(securityToken))), - ValidationErrorType.ArgumentNull)); - } + return new(TokenValidationErrorCommon.NullParameter(nameof(securityToken), 0x123123)); if (validationParameters == null) - { - return new TokenTypeValidationResult( - type, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII(nameof(validationParameters))), - ValidationErrorType.ArgumentNull)); - } + return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123123)); if (validationParameters.ValidTypes.Count == 0) { LogHelper.LogVerbose(LogMessages.IDX10255); - return new TokenTypeValidationResult(type); + return new(new ValidatedTokenType(type ?? "null", validationParameters.ValidTypes.Count)); } if (string.IsNullOrEmpty(type)) - { - return new TokenTypeValidationResult( - type, - ValidationFailureType.TokenTypeValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10256, - LogHelper.MarkAsNonPII(nameof(type))), - ValidationErrorType.SecurityTokenInvalidType)); - } + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidType, + new MessageDetail(LogMessages.IDX10256), + 0x123123, + null)); if (!validationParameters.ValidTypes.Contains(type, StringComparer.Ordinal)) { - return new TokenTypeValidationResult( - type, - ValidationFailureType.TokenTypeValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10257, - LogHelper.MarkAsNonPII(nameof(type)), - LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidTypes))), - ValidationErrorType.SecurityTokenInvalidType)); + return new(new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidType, + new MessageDetail( + LogMessages.IDX10257, + LogHelper.MarkAsNonPII(type), + LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidTypes))), + 0x123123, + null)); } // TODO: Move to CallContext //if (LogHelper.IsEnabled(EventLogLevel.Informational)) // LogHelper.LogInformation(LogMessages.IDX10258, LogHelper.MarkAsNonPII(type)); - return new TokenTypeValidationResult(type); + return new(new ValidatedTokenType(type!, validationParameters.ValidTypes.Count)); } } } From c1e1ee9f65ccbd54006a8f6faa5cba1ac46d6d20 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Tue, 20 Aug 2024 18:22:11 +0100 Subject: [PATCH 07/32] Added project --- ConsoleApp1/ConsoleApp1.csproj | 19 +++++++++++++++++++ ConsoleApp1/Program.cs | 17 +++++++++++++++++ Wilson.sln | 9 +++++++++ 3 files changed, 45 insertions(+) create mode 100644 ConsoleApp1/ConsoleApp1.csproj create mode 100644 ConsoleApp1/Program.cs diff --git a/ConsoleApp1/ConsoleApp1.csproj b/ConsoleApp1/ConsoleApp1.csproj new file mode 100644 index 0000000000..e6b6b29bd2 --- /dev/null +++ b/ConsoleApp1/ConsoleApp1.csproj @@ -0,0 +1,19 @@ + + + + Exe + net8.0 + enable + enable + true + true + True + C:\Users\iinglese\OneDrive - Microsoft\Desktop\ConsoleApp1.snk + + + + + + + + diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs new file mode 100644 index 0000000000..3e8312ab37 --- /dev/null +++ b/ConsoleApp1/Program.cs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.IdentityModel.Benchmarks; + +Console.WriteLine("Hello, World!"); + +var test = new ValidateTokenAsyncWithVPTests(); +test.Setup(); + +var list = new List(); +Console.WriteLine("Size of list: " + list.Capacity); + +for (int i = 0; i < 1000; i++) +{ + test.JsonWebTokenHandler_03_ValidateTokenAsyncWithVP(); +} diff --git a/Wilson.sln b/Wilson.sln index 18274278e0..85ad53a63f 100644 --- a/Wilson.sln +++ b/Wilson.sln @@ -108,6 +108,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{BC99A01F build\version.props = build\version.props EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp1", "ConsoleApp1\ConsoleApp1.csproj", "{DA52E36D-588B-4DF9-A2DD-3442E87938FA}" + ProjectSection(ProjectDependencies) = postProject + {DBF58792-25DF-4B6E-866C-77A0BC5AB81B} = {DBF58792-25DF-4B6E-866C-77A0BC5AB81B} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -238,6 +243,10 @@ Global {F1BB31E4-8865-4425-8BD4-94F1815C16E0}.Debug|Any CPU.Build.0 = Debug|Any CPU {F1BB31E4-8865-4425-8BD4-94F1815C16E0}.Release|Any CPU.ActiveCfg = Release|Any CPU {F1BB31E4-8865-4425-8BD4-94F1815C16E0}.Release|Any CPU.Build.0 = Release|Any CPU + {DA52E36D-588B-4DF9-A2DD-3442E87938FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA52E36D-588B-4DF9-A2DD-3442E87938FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA52E36D-588B-4DF9-A2DD-3442E87938FA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA52E36D-588B-4DF9-A2DD-3442E87938FA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From e89a354b3287eb44d8321a3e2fc1094bce4d858a Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Tue, 20 Aug 2024 18:23:10 +0100 Subject: [PATCH 08/32] Added missing await --- ConsoleApp1/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index 3e8312ab37..13b6e5de93 100644 --- a/ConsoleApp1/Program.cs +++ b/ConsoleApp1/Program.cs @@ -13,5 +13,5 @@ for (int i = 0; i < 1000; i++) { - test.JsonWebTokenHandler_03_ValidateTokenAsyncWithVP(); + await test.JsonWebTokenHandler_03_ValidateTokenAsyncWithVP(); } From ea0fc3c95e4a344e1dd97013004c6a72e28d7166 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Wed, 21 Aug 2024 15:50:01 +0100 Subject: [PATCH 09/32] Removed tags, added implicit initialisers for Result type. Updated Result return values to use implicit initialisation --- .../Result.cs | 24 ++++- .../JsonWebTokenHandler.DecryptToken.cs | 28 +++--- .../JsonWebTokenHandler.ReadToken.cs | 9 +- .../JsonWebTokenHandler.ValidateSignature.cs | 50 ++++------ ...nWebTokenHandler.ValidateToken.Internal.cs | 92 +++++++++---------- .../JwtTokenUtilities.DecryptTokenResult.cs | 15 ++- .../JwtTokenUtilities.cs | 3 - .../Results/TokenValidationError.cs | 43 +++++++-- .../Validation/Validators.Algorithm.cs | 9 +- .../Validation/Validators.Audience.cs | 16 ++-- .../Validation/Validators.Issuer.cs | 23 ++--- .../Validation/Validators.IssuerSigningKey.cs | 21 ++--- .../Validation/Validators.Lifetime.cs | 24 ++--- .../Validation/Validators.TokenReplay.cs | 21 ++--- .../Validation/Validators.TokenType.cs | 18 ++-- 15 files changed, 202 insertions(+), 194 deletions(-) diff --git a/src/Microsoft.IdentityModel.Abstractions/Result.cs b/src/Microsoft.IdentityModel.Abstractions/Result.cs index 11062f8e96..8eeb19d35d 100644 --- a/src/Microsoft.IdentityModel.Abstractions/Result.cs +++ b/src/Microsoft.IdentityModel.Abstractions/Result.cs @@ -38,6 +38,18 @@ public Result(TError error) IsSuccess = false; } + /// + /// Creates a successful result implicitly from the value. + /// + /// The value to be stored in the result. + public static implicit operator Result(TResult result) => new(result); + + /// + /// Creates an error result implicitly from the error value. + /// + /// The error to be stored in the result. + public static implicit operator Result(TError error) => new(error); + /// /// Gets a value indicating whether the result is successful. /// @@ -49,7 +61,7 @@ public Result(TError error) /// The wrapped result value. /// This method is only valid if the result type is successful. /// Thrown if attempted to unwrap the value from a failed result. - public TResult Unwrap() => IsSuccess ? _result! : throw new InvalidOperationException("Cannot unwrap error result"); + public TResult UnwrapResult() => IsSuccess ? _result! : throw new InvalidOperationException("Cannot unwrap error result"); /// /// Unwraps the error. @@ -124,6 +136,16 @@ public bool Equals(Result other) else return _error!.Equals(other._error); } + + /// + /// Casts the result to a . + /// # + /// Required for compatibility, see CA2225 for more information + /// The existing instance. + public Result ToResult() + { + return this; + } } } #nullable restore diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs index e7e4df70e7..f093f96c4e 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs @@ -30,31 +30,30 @@ internal Result DecryptToken( CallContext? callContext) { if (jwtToken == null) - return new(TokenValidationErrorCommon.NullParameter(nameof(jwtToken), 0x123123)); + return TokenValidationErrorCommon.NullParameter(nameof(jwtToken)); if (validationParameters == null) - return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123124)); + return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); if (string.IsNullOrEmpty(jwtToken.Enc)) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenDecryptionFailed, new MessageDetail(TokenLogMessages.IDX10612), - Tag: 0x123125, - null)); + null); - var keysOrExceptionDetail = GetContentEncryptionKeys(jwtToken, validationParameters, configuration, callContext); - if (keysOrExceptionDetail.Item2 != null) // TokenValidationError returned - return new(keysOrExceptionDetail.Item2); + (IList? contentEncryptionKeys, TokenValidationError? validationError) result = + GetContentEncryptionKeys(jwtToken, validationParameters, configuration, callContext); - var keys = keysOrExceptionDetail.Item1; - if (keys == null) - return new(new TokenValidationError( + if (result.validationError != null) + return result.validationError; + + if (result.contentEncryptionKeys == null) + return new TokenValidationError( ValidationErrorType.SecurityTokenKeyWrap, new MessageDetail( TokenLogMessages.IDX10609, LogHelper.MarkAsSecurityArtifact(jwtToken, JwtTokenUtilities.SafeLogJwtToken)), - Tag: 0x123126, - null)); + null); return JwtTokenUtilities.DecryptJwtToken( jwtToken, @@ -62,7 +61,7 @@ internal Result DecryptToken( new JwtTokenDecryptionParameters { DecompressionFunction = JwtTokenUtilities.DecompressToken, - Keys = keys, + Keys = result.contentEncryptionKeys, MaximumDeflateSize = MaximumTokenSizeInBytes }, callContext); @@ -192,7 +191,6 @@ internal Result DecryptToken( keysAttempted?.ToString() ?? "", exceptionStrings?.ToString() ?? "", LogHelper.MarkAsSecurityArtifact(jwtToken, JwtTokenUtilities.SafeLogJwtToken)), - Tag: 0x123126, null); return (null, tokenValidationError); diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs index e4c242738c..0fc5e04a7e 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs @@ -27,22 +27,21 @@ internal static Result ReadToken( #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging { if (String.IsNullOrEmpty(token)) - return new(TokenValidationErrorCommon.NullParameter(nameof(token), 0x123123)); + return TokenValidationErrorCommon.NullParameter(nameof(token)); try { JsonWebToken jsonWebToken = new JsonWebToken(token); - return new(jsonWebToken); + return jsonWebToken; } #pragma warning disable CA1031 // Do not catch general exception types catch #pragma warning restore CA1031 // Do not catch general exception types { - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenMalformed, new MessageDetail(LogMessages.IDX14107), - Tag: 0x123456, - null)); + null); } } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs index f3ca3268e0..1d99f43b3f 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs @@ -34,10 +34,10 @@ internal static Result ValidateSignature( CallContext callContext) { if (jwtToken is null) - return new(TokenValidationErrorCommon.NullParameter(nameof(jwtToken), 0x123123)); + return TokenValidationErrorCommon.NullParameter(nameof(jwtToken)); if (validationParameters is null) - return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123123)); + return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); // Delegate is set by the user, we call it and return the result. if (validationParameters.SignatureValidator is not null) @@ -45,15 +45,14 @@ internal static Result ValidateSignature( // If the user wants to accept unsigned tokens, they must implement the delegate. if (!jwtToken.IsSigned) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenInvalidSignature, new MessageDetail( TokenLogMessages.IDX10504, LogHelper.MarkAsSecurityArtifact( jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - 0x123123, - null)); + null); SecurityKey? key = null; if (validationParameters.IssuerSigningKeyResolver is not null) @@ -86,11 +85,10 @@ internal static Result ValidateSignature( if (validationParameters.TryAllIssuerSigningKeys) return ValidateSignatureUsingAllKeys(jwtToken, validationParameters, configuration, callContext); else - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenSignatureKeyNotFound, new MessageDetail(TokenLogMessages.IDX10500), - 0x123123, - null)); + null); } private static Result ValidateSignatureUsingAllKeys( @@ -122,11 +120,10 @@ private static Result ValidateSignatureUsing return unwrappedVpResult; if (vpFailedResult is null && configFailedResult is null) // No keys were attempted - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenSignatureKeyNotFound, new MessageDetail(TokenLogMessages.IDX10500), - 0x123123, - null)); + null); StringBuilder exceptionStrings = new(); StringBuilder keysAttempted = new(); @@ -138,14 +135,14 @@ private static Result ValidateSignatureUsing bool kidMatched = configKidMatched || vpKidMatched; // No valid signature found. Return the exception details. - return new(GetSignatureValidationError( + return GetSignatureValidationError( jwtToken, validationParameters, configuration, exceptionStrings, keysAttempted, kidExists, - kidMatched)); + kidMatched); } private static (Result? validResult, bool KidMatched, KeyMatchFailedResult? failedResult) ValidateUsingKeys( @@ -201,14 +198,13 @@ private static Result ValidateSignatureWithK CryptoProviderFactory cryptoProviderFactory = validationParameters.CryptoProviderFactory ?? key.CryptoProviderFactory; if (!cryptoProviderFactory.IsSupportedAlgorithm(jsonWebToken.Alg, key)) { - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenInvalidAlgorithm, new MessageDetail( LogMessages.IDX14000, LogHelper.MarkAsNonPII(jsonWebToken.Alg), key), - 0x123123, - null)); + null); } Result result = validationParameters.AlgorithmValidator( @@ -219,20 +215,19 @@ private static Result ValidateSignatureWithK callContext); if (!result.IsSuccess) - return new(result.UnwrapError()); + return new(result.UnwrapError()); // Because we return an interface type, we need to explicitly create the Result. SignatureProvider signatureProvider = cryptoProviderFactory.CreateForVerifying(key, jsonWebToken.Alg); try { if (signatureProvider == null) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.InvalidOperation, new MessageDetail( TokenLogMessages.IDX10636, key?.ToString() ?? "Null", LogHelper.MarkAsNonPII(jsonWebToken.Alg)), - 0x123123, - null)); + null); bool valid = EncodingUtils.PerformEncodingDependentOperation( jsonWebToken.EncodedToken, @@ -245,31 +240,29 @@ private static Result ValidateSignatureWithK ValidateSignature); if (valid) - return new(key); + return key; else - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenInvalidSignature, new MessageDetail( TokenLogMessages.IDX10504, LogHelper.MarkAsSecurityArtifact( jsonWebToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - 0x123123, - null)); + null); } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenInvalidSignature, new MessageDetail( TokenLogMessages.IDX10504, LogHelper.MarkAsSecurityArtifact( jsonWebToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - 0x123123, - ex)); + ex); } finally { @@ -308,7 +301,6 @@ private static TokenValidationError GetSignatureValidationError( LogHelper.MarkAsNonPII(jwtToken.Kid), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - 0x1232123, null); } @@ -323,7 +315,6 @@ private static TokenValidationError GetSignatureValidationError( LogHelper.MarkAsNonPII(numKeysInConfiguration), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - 0x1232123, null); return new TokenValidationError( @@ -335,7 +326,6 @@ private static TokenValidationError GetSignatureValidationError( LogHelper.MarkAsNonPII(numKeysInConfiguration), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - 0x1232123, null); } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs index 4f6ce39fd5..4be8e61e9d 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs @@ -45,14 +45,14 @@ internal async Task ValidateTokenAsync( null, this, validationParameters, - TokenValidationErrorCommon.NullParameter(nameof(token), tag: 0x121211)); + TokenValidationErrorCommon.NullParameter(nameof(token))); if (validationParameters is null) return new ValidationResult( null, this, validationParameters, - TokenValidationErrorCommon.NullParameter(nameof(validationParameters), tag: 0x121212)); + TokenValidationErrorCommon.NullParameter(nameof(validationParameters))); if (token.Length > MaximumTokenSizeInBytes) return new ValidationResult( @@ -62,13 +62,12 @@ internal async Task ValidateTokenAsync( new TokenValidationError( ValidationErrorType.InvalidArgument, new MessageDetail(TokenLogMessages.IDX10209, LogHelper.MarkAsNonPII(token.Length), LogHelper.MarkAsNonPII(MaximumTokenSizeInBytes)), - Tag: 0x121213, null)); Result result = ReadToken(token, callContext); if (result.IsSuccess) return await ValidateTokenAsync( - result.Unwrap(), + result.UnwrapResult(), validationParameters, callContext, cancellationToken) @@ -93,14 +92,14 @@ internal async Task ValidateTokenAsync( token, this, validationParameters, - TokenValidationErrorCommon.NullParameter(nameof(token), tag: 0x121211)); + TokenValidationErrorCommon.NullParameter(nameof(token))); if (validationParameters is null) return new ValidationResult( token, this, validationParameters, - TokenValidationErrorCommon.NullParameter(nameof(validationParameters), tag: 0x121212)); + TokenValidationErrorCommon.NullParameter(nameof(validationParameters))); if (token is not JsonWebToken jwt) return new ValidationResult( @@ -110,7 +109,6 @@ internal async Task ValidateTokenAsync( new TokenValidationError( ValidationErrorType.InvalidArgument, new MessageDetail(TokenLogMessages.IDX10001, nameof(token), nameof(JsonWebToken)), - Tag: 0x121214, null)); return await InternalValidateTokenAsync( @@ -225,12 +223,12 @@ private async ValueTask ValidateJWEAsync( if (!decryptionResult.IsSuccess) return new ValidationResult(jwtToken, this, validationParameters, decryptionResult.UnwrapError()); - Result readResult = ReadToken(decryptionResult.Unwrap(), callContext); + Result readResult = ReadToken(decryptionResult.UnwrapResult(), callContext); if (!readResult.IsSuccess) return new ValidationResult(jwtToken, this, validationParameters, readResult.UnwrapError()); - JsonWebToken decryptedToken = readResult.Unwrap() as JsonWebToken; + JsonWebToken decryptedToken = readResult.UnwrapResult() as JsonWebToken; ValidationResult validationResult = await ValidateJWSAsync(decryptedToken, validationParameters, configuration, callContext, cancellationToken) @@ -270,7 +268,7 @@ private async ValueTask ValidateJWSAsync( if (!audienceValidationResult.IsSuccess) return new ValidationResult(jsonWebToken, this, validationParameters, audienceValidationResult.UnwrapError()) { - ValidatedLifetime = lifetimeValidationResult.Unwrap() + ValidatedLifetime = lifetimeValidationResult.UnwrapResult() }; Result issuerValidationResult = await validationParameters.IssuerValidatorAsync( @@ -280,8 +278,8 @@ private async ValueTask ValidateJWSAsync( if (!issuerValidationResult.IsSuccess) return new ValidationResult(jsonWebToken, this, validationParameters, issuerValidationResult.UnwrapError()) { - ValidatedLifetime = lifetimeValidationResult.Unwrap(), - ValidatedAudience = audienceValidationResult.Unwrap() + ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), + ValidatedAudience = audienceValidationResult.UnwrapResult() }; Result replayValidationResult = validationParameters.TokenReplayValidator( @@ -290,9 +288,9 @@ private async ValueTask ValidateJWSAsync( if (!replayValidationResult.IsSuccess) return new ValidationResult(jsonWebToken, this, validationParameters, replayValidationResult.UnwrapError()) { - ValidatedLifetime = lifetimeValidationResult.Unwrap(), - ValidatedAudience = audienceValidationResult.Unwrap(), - ValidatedIssuer = issuerValidationResult.Unwrap() + ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), + ValidatedAudience = audienceValidationResult.UnwrapResult(), + ValidatedIssuer = issuerValidationResult.UnwrapResult() }; ValidationResult actorValidationResult = null; @@ -303,13 +301,13 @@ private async ValueTask ValidateJWSAsync( if (!actorReadingResult.IsSuccess) return new ValidationResult(jsonWebToken, this, validationParameters, actorReadingResult.UnwrapError()) { - ValidatedLifetime = lifetimeValidationResult.Unwrap(), - ValidatedAudience = audienceValidationResult.Unwrap(), - ValidatedIssuer = issuerValidationResult.Unwrap(), - ValidatedTokenReplayExpirationTime = replayValidationResult.Unwrap() + ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), + ValidatedAudience = audienceValidationResult.UnwrapResult(), + ValidatedIssuer = issuerValidationResult.UnwrapResult(), + ValidatedTokenReplayExpirationTime = replayValidationResult.UnwrapResult() }; - JsonWebToken actorToken = actorReadingResult.Unwrap() as JsonWebToken; + JsonWebToken actorToken = actorReadingResult.UnwrapResult() as JsonWebToken; ValidationParameters actorParameters = validationParameters.ActorValidationParameters; actorValidationResult = await ValidateJWSAsync(actorToken, actorParameters, configuration, callContext, cancellationToken) @@ -320,10 +318,10 @@ await ValidateJWSAsync(actorToken, actorParameters, configuration, callContext, if (!actorValidationResult.IsValid) return new ValidationResult(jsonWebToken, this, validationParameters, actorValidationResult.TokenValidationError) { - ValidatedLifetime = lifetimeValidationResult.Unwrap(), - ValidatedAudience = audienceValidationResult.Unwrap(), - ValidatedIssuer = issuerValidationResult.Unwrap(), - ValidatedTokenReplayExpirationTime = replayValidationResult.Unwrap(), + ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), + ValidatedAudience = audienceValidationResult.UnwrapResult(), + ValidatedIssuer = issuerValidationResult.UnwrapResult(), + ValidatedTokenReplayExpirationTime = replayValidationResult.UnwrapResult(), ActorValidationResult = actorValidationResult }; } @@ -334,10 +332,10 @@ await ValidateJWSAsync(actorToken, actorParameters, configuration, callContext, if (!typeValidationResult.IsSuccess) return new ValidationResult(jsonWebToken, this, validationParameters, typeValidationResult.UnwrapError()) { - ValidatedLifetime = lifetimeValidationResult.Unwrap(), - ValidatedAudience = audienceValidationResult.Unwrap(), - ValidatedIssuer = issuerValidationResult.Unwrap(), - ValidatedTokenReplayExpirationTime = replayValidationResult.Unwrap(), + ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), + ValidatedAudience = audienceValidationResult.UnwrapResult(), + ValidatedIssuer = issuerValidationResult.UnwrapResult(), + ValidatedTokenReplayExpirationTime = replayValidationResult.UnwrapResult(), ActorValidationResult = actorValidationResult }; @@ -348,39 +346,39 @@ await ValidateJWSAsync(actorToken, actorParameters, configuration, callContext, if (!signatureValidationResult.IsSuccess) return new ValidationResult(jsonWebToken, this, validationParameters, signatureValidationResult.UnwrapError()) { - ValidatedLifetime = lifetimeValidationResult.Unwrap(), - ValidatedAudience = audienceValidationResult.Unwrap(), - ValidatedIssuer = issuerValidationResult.Unwrap(), - ValidatedTokenReplayExpirationTime = replayValidationResult.Unwrap(), + ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), + ValidatedAudience = audienceValidationResult.UnwrapResult(), + ValidatedIssuer = issuerValidationResult.UnwrapResult(), + ValidatedTokenReplayExpirationTime = replayValidationResult.UnwrapResult(), ActorValidationResult = actorValidationResult, - ValidatedTokenType = typeValidationResult.Unwrap() + ValidatedTokenType = typeValidationResult.UnwrapResult() }; Result issuerSigningKeyValidationResult = validationParameters.IssuerSigningKeyValidator( - signatureValidationResult.Unwrap(), jsonWebToken, validationParameters, configuration, callContext); + signatureValidationResult.UnwrapResult(), jsonWebToken, validationParameters, configuration, callContext); if (!issuerSigningKeyValidationResult.IsSuccess) return new ValidationResult(jsonWebToken, this, validationParameters, issuerSigningKeyValidationResult.UnwrapError()) { - ValidatedLifetime = lifetimeValidationResult.Unwrap(), - ValidatedAudience = audienceValidationResult.Unwrap(), - ValidatedIssuer = issuerValidationResult.Unwrap(), - ValidatedTokenReplayExpirationTime = replayValidationResult.Unwrap(), + ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), + ValidatedAudience = audienceValidationResult.UnwrapResult(), + ValidatedIssuer = issuerValidationResult.UnwrapResult(), + ValidatedTokenReplayExpirationTime = replayValidationResult.UnwrapResult(), ActorValidationResult = actorValidationResult, - ValidatedTokenType = typeValidationResult.Unwrap(), - ValidatedSigningKey = signatureValidationResult.Unwrap() + ValidatedTokenType = typeValidationResult.UnwrapResult(), + ValidatedSigningKey = signatureValidationResult.UnwrapResult() }; return new(jsonWebToken, this, validationParameters) { - ValidatedLifetime = lifetimeValidationResult.Unwrap(), - ValidatedAudience = audienceValidationResult.Unwrap(), - ValidatedIssuer = issuerValidationResult.Unwrap(), - ValidatedTokenReplayExpirationTime = replayValidationResult.Unwrap(), + ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), + ValidatedAudience = audienceValidationResult.UnwrapResult(), + ValidatedIssuer = issuerValidationResult.UnwrapResult(), + ValidatedTokenReplayExpirationTime = replayValidationResult.UnwrapResult(), ActorValidationResult = actorValidationResult, - ValidatedTokenType = typeValidationResult.Unwrap(), - ValidatedSigningKey = signatureValidationResult.Unwrap(), - ValidatedSigningKeyLifetime = issuerSigningKeyValidationResult.Unwrap() + ValidatedTokenType = typeValidationResult.UnwrapResult(), + ValidatedSigningKey = signatureValidationResult.UnwrapResult(), + ValidatedSigningKeyLifetime = issuerSigningKeyValidationResult.UnwrapResult() }; } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs index 2cb41ffaa4..24a6182d46 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs @@ -27,10 +27,10 @@ internal static Result DecryptJwtToken( CallContext callContext) { if (validationParameters == null) - return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123141)); + return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); if (decryptionParameters == null) - return new(TokenValidationErrorCommon.NullParameter(nameof(decryptionParameters), 0x123142)); + return TokenValidationErrorCommon.NullParameter(nameof(decryptionParameters)); bool decryptionSucceeded = false; bool algorithmNotSupportedByCryptoProvider = false; @@ -96,12 +96,12 @@ internal static Result DecryptJwtToken( } if (!decryptionSucceeded) - return new(GetDecryptionError( + return GetDecryptionError( decryptionParameters, algorithmNotSupportedByCryptoProvider, exceptionStrings, keysAttempted, - callContext)); + callContext); try { @@ -111,17 +111,16 @@ internal static Result DecryptJwtToken( else decodedString = decryptionParameters.DecompressionFunction(decryptedTokenBytes, zipAlgorithm, decryptionParameters.MaximumDeflateSize); - return new(decodedString); + return decodedString; } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenDecompressionFailed, new MessageDetail(TokenLogMessages.IDX10679, zipAlgorithm), - 0x123123, - ex)); + ex); } } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs index fb7f34a9b0..f0928af793 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs @@ -371,7 +371,6 @@ private static TokenValidationError GetDecryptionError( keysAttempted.ToString(), exceptionStrings?.ToString() ?? string.Empty, LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken)), - Tag: 0x123456, null); else if (algorithmNotSupportedByCryptoProvider) return new TokenValidationError( @@ -380,7 +379,6 @@ private static TokenValidationError GetDecryptionError( TokenLogMessages.IDX10619, LogHelper.MarkAsNonPII(decryptionParameters.Alg), LogHelper.MarkAsNonPII(decryptionParameters.Enc)), - Tag: 0x123456, null); else return new TokenValidationError( @@ -388,7 +386,6 @@ private static TokenValidationError GetDecryptionError( new MessageDetail( TokenLogMessages.IDX10609, LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken)), - Tag: 0x123456, null); } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs index 6abeaa2e31..eaca50bb66 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs @@ -4,6 +4,8 @@ #nullable enable using System; +//using System.Diagnostics; +using System.Runtime.CompilerServices; namespace Microsoft.IdentityModel.Tokens { @@ -11,17 +13,34 @@ internal interface ITokenValidationError { ValidationErrorType ErrorType { get; } MessageDetail MessageDetail { get; } - int Tag { get; } - Exception? InnerException { get; } } - internal record struct TokenValidationError( - ValidationErrorType ErrorType, - MessageDetail MessageDetail, - int Tag, - Exception? InnerException) : ITokenValidationError + internal struct TokenValidationError : ITokenValidationError { + public ValidationErrorType ErrorType { get; } + public MessageDetail MessageDetail { get; } + public Exception? InnerException { get; } + public string CallerFilePath { get; } + public int CallerLineNumber { get; } + + //private StackFrame? _stackFrame; + + public TokenValidationError( + ValidationErrorType errorType, + MessageDetail messageDetail, + Exception? innerException, + [CallerFilePath] string callerFilePath = "", + [CallerLineNumber] int callerLineNumber = 0) + { + ErrorType = errorType; + MessageDetail = messageDetail; + InnerException = innerException; + CallerFilePath = callerFilePath; + CallerLineNumber = callerLineNumber; + + //_stackFrame = new StackFrame(); + } } /// @@ -33,10 +52,14 @@ public static class TokenValidationErrorCommon /// /// /// - /// /// - internal static TokenValidationError NullParameter(string parameterName, int tag) - => new(ValidationErrorType.ArgumentNull, MessageDetail.NullParameter(parameterName), tag, null); + internal static TokenValidationError NullParameter( + string parameterName, +#pragma warning disable CS1573 // Parameter has no matching param tag in the XML comment (but other parameters do) + [CallerFilePath] string callerFilePath = "", + [CallerLineNumber] int callerLineNumber = 0) +#pragma warning restore CS1573 // Parameter has no matching param tag in the XML comment (but other parameters do) + => new(ValidationErrorType.ArgumentNull, MessageDetail.NullParameter(parameterName), null, callerFilePath, callerLineNumber); } internal enum ValidationErrorType diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs index 05fd244453..e85a6e84c0 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs @@ -46,18 +46,17 @@ internal static Result ValidateAlgorithm( #pragma warning restore CA1801 // TODO: remove pragma disable once callContext is used for logging { if (validationParameters == null) - return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123123)); + return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); if (validationParameters.ValidAlgorithms != null && validationParameters.ValidAlgorithms.Count > 0 && !validationParameters.ValidAlgorithms.Contains(algorithm, StringComparer.Ordinal)) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenInvalidAlgorithm, new MessageDetail( LogMessages.IDX10696, LogHelper.MarkAsNonPII(algorithm)), - 0x123123, - null)); + null); - return new(algorithm); + return algorithm; } } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs index 71cc2e1c2e..0492afa981 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs @@ -46,30 +46,28 @@ internal static Result ValidateAudience(IList tokenAudiences, IList validAudiences, bool ignoreTrailingSlashWhenValidatingAudience) diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs index 1036c613eb..b13184c9a2 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs @@ -63,17 +63,16 @@ internal static async Task> Valid CancellationToken? cancellationToken) { if (string.IsNullOrWhiteSpace(issuer)) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenInvalidIssuer, new MessageDetail(LogMessages.IDX10211), - 0x123123, - null)); + null); if (validationParameters == null) - return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123123)); + return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); if (securityToken == null) - return new(TokenValidationErrorCommon.NullParameter(nameof(securityToken), 0x123123)); + return TokenValidationErrorCommon.NullParameter(nameof(securityToken)); BaseConfiguration? configuration = null; if (validationParameters.ConfigurationManager != null) @@ -81,11 +80,10 @@ internal static async Task> Valid // Return failed IssuerValidationResult if all possible places to validate against are null or empty. if (validationParameters.ValidIssuers.Count == 0 && string.IsNullOrWhiteSpace(configuration?.Issuer)) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenInvalidIssuer, new MessageDetail(LogMessages.IDX10211), - 0x123123, - null)); + null); if (configuration != null) { @@ -99,7 +97,7 @@ internal static async Task> Valid // LogHelper.LogInformation(LogMessages.IDX10236, LogHelper.MarkAsNonPII(issuer), callContext); - return new(new ValidatedIssuer(issuer, IssuerValidationSource.IssuerIsConfigurationIssuer)); + return new ValidatedIssuer(issuer, IssuerValidationSource.IssuerIsConfigurationIssuer); } } @@ -122,20 +120,19 @@ internal static async Task> Valid //if (LogHelper.IsEnabled(EventLogLevel.Informational)) // LogHelper.LogInformation(LogMessages.IDX10236, LogHelper.MarkAsNonPII(issuer)); - return new(new ValidatedIssuer(issuer, IssuerValidationSource.IssuerIsAmongValidIssuers)); + return new ValidatedIssuer(issuer, IssuerValidationSource.IssuerIsAmongValidIssuers); } } } - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenInvalidIssuer, new MessageDetail( LogMessages.IDX10212, LogHelper.MarkAsNonPII(issuer), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidIssuers)), LogHelper.MarkAsNonPII(configuration?.Issuer)), - 0x123123, - null)); + null); } } #nullable restore diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs index b707bc2fa2..6033d385c6 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs @@ -57,19 +57,18 @@ internal static Result Valid CallContext? callContext) { if (validationParameters == null) - return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123123)); + return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); if (securityKey == null) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.ArgumentNull, new MessageDetail( LogMessages.IDX10253, nameof(securityKey)), - 0x123123, - null)); + null); if (securityToken == null) - return new(TokenValidationErrorCommon.NullParameter(nameof(securityToken), 0x123123)); + return TokenValidationErrorCommon.NullParameter(nameof(securityToken)); return ValidateIssuerSigningKeyLifeTime(securityKey, validationParameters, callContext); } @@ -98,35 +97,33 @@ internal static Result Valid notAfterUtc = cert.NotAfter.ToUniversalTime(); if (notBeforeUtc > DateTimeUtil.Add(utcNow, validationParameters.ClockSkew)) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenInvalidSigningKey, new MessageDetail( LogMessages.IDX10248, LogHelper.MarkAsNonPII(notBeforeUtc), LogHelper.MarkAsNonPII(utcNow)), - 0x123123, - null)); + null); //TODO: Move to CallContext //if (LogHelper.IsEnabled(EventLogLevel.Informational)) // LogHelper.LogInformation(LogMessages.IDX10250, LogHelper.MarkAsNonPII(notBeforeUtc), LogHelper.MarkAsNonPII(utcNow)); if (notAfterUtc < DateTimeUtil.Add(utcNow, validationParameters.ClockSkew.Negate())) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenInvalidSigningKey, new MessageDetail( LogMessages.IDX10249, LogHelper.MarkAsNonPII(notAfterUtc), LogHelper.MarkAsNonPII(utcNow)), - 0x123123, - null)); + null); // TODO: Move to CallContext //if (LogHelper.IsEnabled(EventLogLevel.Informational)) // LogHelper.LogInformation(LogMessages.IDX10251, LogHelper.MarkAsNonPII(notAfterUtc), LogHelper.MarkAsNonPII(utcNow)); } - return new(new ValidatedSigningKeyLifetime(notBeforeUtc, notAfterUtc, utcNow)); + return new ValidatedSigningKeyLifetime(notBeforeUtc, notAfterUtc, utcNow); } } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs index 3d9dfafdd3..559bc11d3e 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs @@ -57,53 +57,49 @@ internal static Result ValidateLifetim #pragma warning restore CA1801 { if (validationParameters == null) - return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123123)); + return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); if (!expires.HasValue) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenNoExpiration, new MessageDetail( LogMessages.IDX10225, LogHelper.MarkAsNonPII(securityToken == null ? "null" : securityToken.GetType().ToString())), - 0x123123, - null)); + null); if (notBefore.HasValue && expires.HasValue && (notBefore.Value > expires.Value)) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenInvalidLifetime, new MessageDetail( LogMessages.IDX10224, LogHelper.MarkAsNonPII(notBefore.Value), LogHelper.MarkAsNonPII(expires.Value)), - 0x123123, - null)); + null); DateTime utcNow = DateTime.UtcNow; if (notBefore.HasValue && (notBefore.Value > DateTimeUtil.Add(utcNow, validationParameters.ClockSkew))) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenNotYetValid, new MessageDetail( LogMessages.IDX10222, LogHelper.MarkAsNonPII(notBefore.Value), LogHelper.MarkAsNonPII(utcNow)), - 0x123123, - null)); + null); if (expires.HasValue && (expires.Value < DateTimeUtil.Add(utcNow, validationParameters.ClockSkew.Negate()))) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenExpired, new MessageDetail( LogMessages.IDX10223, LogHelper.MarkAsNonPII(expires.Value), LogHelper.MarkAsNonPII(utcNow)), - 0x123123, - null)); + null); // if it reaches here, that means lifetime of the token is valid if (LogHelper.IsEnabled(EventLogLevel.Informational)) LogHelper.LogInformation(LogMessages.IDX10239); - return new(new ValidatedLifetime(notBefore, expires)); + return new ValidatedLifetime(notBefore, expires); } } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs index 522065685f..b5f390a19c 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs @@ -44,46 +44,43 @@ public static partial class Validators #pragma warning restore CA1801 // Review unused parameters { if (string.IsNullOrWhiteSpace(securityToken)) - return new(TokenValidationErrorCommon.NullParameter(nameof(securityToken), 0x123123)); + return TokenValidationErrorCommon.NullParameter(nameof(securityToken)); if (validationParameters == null) - return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123123)); + return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); // check if token if replay cache is set, then there must be an expiration time. if (validationParameters.TokenReplayCache != null) { if (expirationTime == null) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenReplayDetected, new MessageDetail( LogMessages.IDX10227, LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), - 0x123123, - null)); + null); if (validationParameters.TokenReplayCache.TryFind(securityToken)) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenReplayDetected, new MessageDetail( LogMessages.IDX10228, LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), - 0x123123, - null)); + null); if (!validationParameters.TokenReplayCache.TryAdd(securityToken, expirationTime.Value)) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenReplayAddFailed, new MessageDetail( LogMessages.IDX10229, LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), - 0x123123, - null)); + null); } // if it reaches here, that means no token replay is detected. // TODO: Move to CallContext //LogHelper.LogInformation(LogMessages.IDX10240); - return new(expirationTime); + return expirationTime; } } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs index 676e1a361a..35a4c667d4 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs @@ -47,41 +47,39 @@ internal static Result ValidateTokenT #pragma warning restore CA1801 // TODO: remove pragma disable once callContext is used for logging { if (securityToken == null) - return new(TokenValidationErrorCommon.NullParameter(nameof(securityToken), 0x123123)); + return TokenValidationErrorCommon.NullParameter(nameof(securityToken)); if (validationParameters == null) - return new(TokenValidationErrorCommon.NullParameter(nameof(validationParameters), 0x123123)); + return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); if (validationParameters.ValidTypes.Count == 0) { LogHelper.LogVerbose(LogMessages.IDX10255); - return new(new ValidatedTokenType(type ?? "null", validationParameters.ValidTypes.Count)); + return new ValidatedTokenType(type ?? "null", validationParameters.ValidTypes.Count); } if (string.IsNullOrEmpty(type)) - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenInvalidType, new MessageDetail(LogMessages.IDX10256), - 0x123123, - null)); + null); if (!validationParameters.ValidTypes.Contains(type, StringComparer.Ordinal)) { - return new(new TokenValidationError( + return new TokenValidationError( ValidationErrorType.SecurityTokenInvalidType, new MessageDetail( LogMessages.IDX10257, LogHelper.MarkAsNonPII(type), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidTypes))), - 0x123123, - null)); + null); } // TODO: Move to CallContext //if (LogHelper.IsEnabled(EventLogLevel.Informational)) // LogHelper.LogInformation(LogMessages.IDX10258, LogHelper.MarkAsNonPII(type)); - return new(new ValidatedTokenType(type!, validationParameters.ValidTypes.Count)); + return new ValidatedTokenType(type!, validationParameters.ValidTypes.Count); } } } From d87e8dcf972127bf80e28d0f216777f03fb81724 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Wed, 21 Aug 2024 17:55:47 +0100 Subject: [PATCH 10/32] Removed IdentityComparer methods relating to removed result types. Updated tests for Algorithm and Audience validation --- .../Validation/Validators.Issuer.cs | 1 - .../IdentityComparer.cs | 689 +----------------- .../InternalsVisibleTo.cs | 5 + .../AlgorithmValidationResultTests.cs | 64 +- .../AudienceValidationResultTests.cs | 495 +++++-------- 5 files changed, 243 insertions(+), 1011 deletions(-) create mode 100644 test/Microsoft.IdentityModel.TestUtils/InternalsVisibleTo.cs diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs index b13184c9a2..e3a0892aef 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs @@ -15,7 +15,6 @@ internal enum IssuerValidationSource { NotValidated = 0, IssuerIsConfigurationIssuer, - IssuerIsValidIssuer, IssuerIsAmongValidIssuers } diff --git a/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs b/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs index f4379d7cc7..4c96a3150a 100644 --- a/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs +++ b/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs @@ -21,7 +21,6 @@ using System.Text.Json; using System.Text.RegularExpressions; using Microsoft.IdentityModel.JsonWebTokens; -using Microsoft.IdentityModel.JsonWebTokens.Results; using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Protocols.WsFederation; @@ -64,7 +63,6 @@ public class IdentityComparer { typeof(IEnumerable).ToString(), AreX509DataEnumsEqual }, { typeof(int).ToString(), AreIntsEqual }, { typeof(IssuerSerial).ToString(), CompareAllPublicProperties }, - { typeof(IssuerValidationResult).ToString(), AreIssuerValidationResultsEqual }, { typeof(JArray).ToString(), AreJArraysEqual }, { typeof(JObject).ToString(), AreJObjectsEqual }, { typeof(JsonElement).ToString(), AreJsonElementsEqual }, @@ -158,73 +156,6 @@ public class IdentityComparer }; // Keep methods in alphabetical order - - public static bool AreAlgorithmValidationResultsEqual(object object1, object object2, CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(object1, object2, context)) - return context.Merge(localContext); - - return AreAlgorithmValidationResultsEqual( - object1 as AlgorithmValidationResult, - object2 as AlgorithmValidationResult, - "AlgorithmValidationResult1", - "AlgorithmValidationResult2", - null, - context); - } - - internal static bool AreAlgorithmValidationResultsEqual( - AlgorithmValidationResult algorithmValidationResult1, - AlgorithmValidationResult algorithmValidationResult2, - string name1, - string name2, - string stackPrefix, - CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(algorithmValidationResult1, algorithmValidationResult2, localContext)) - return context.Merge(localContext); - - if (algorithmValidationResult1.Algorithm != algorithmValidationResult2.Algorithm) - localContext.Diffs.Add($"AlgorithmValidationResult1.Algorithm: '{algorithmValidationResult1.Algorithm}' != AlgorithmValidationResult2.Algorithm: '{algorithmValidationResult2.Algorithm}'"); - - if (algorithmValidationResult1.IsValid != algorithmValidationResult2.IsValid) - localContext.Diffs.Add($"AlgorithmValidationResult1.IsValid: {algorithmValidationResult1.IsValid} != AlgorithmValidationResult2.IsValid: {algorithmValidationResult2.IsValid}"); - - if (algorithmValidationResult1.ValidationFailureType != algorithmValidationResult2.ValidationFailureType) - localContext.Diffs.Add($"AlgorithmValidationResult1.ValidationFailureType: {algorithmValidationResult1.ValidationFailureType} != AlgorithmValidationResult2.ValidationFailureType: {algorithmValidationResult2.ValidationFailureType}"); - - // true => both are not null. - if (ContinueCheckingEquality(algorithmValidationResult1.Exception, algorithmValidationResult2.Exception, localContext)) - { - AreStringsEqual( - algorithmValidationResult1.Exception.Message, - algorithmValidationResult2.Exception.Message, - $"({name1}).Exception.Message", - $"({name2}).Exception.Message", - localContext); - - AreStringsEqual( - algorithmValidationResult1.Exception.Source, - algorithmValidationResult2.Exception.Source, - $"({name1}).Exception.Source", - $"({name2}).Exception.Source", - localContext); - - if (!string.IsNullOrEmpty(stackPrefix)) - AreStringPrefixesEqual( - algorithmValidationResult1.Exception.StackTrace.Trim(), - algorithmValidationResult2.Exception.StackTrace.Trim(), - $"({name1}).Exception.StackTrace", - $"({name2}).Exception.StackTrace", - stackPrefix.Trim(), - localContext); - } - - return context.Merge(localContext); - } - public static bool AreBoolsEqual(object object1, object object2, CompareContext context) { return AreBoolsEqual(object1, object2, "bool1", "bool2", context); @@ -614,546 +545,6 @@ public static bool AreEqual(object object1, object object2, CompareContext conte return context.Merge(localContext); } - public static bool AreIssuerValidationResultsEqual(object object1, object object2, CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(object1, object2, context)) - return context.Merge(localContext); - - return AreIssuerValidationResultsEqual( - object1 as IssuerValidationResult, - object2 as IssuerValidationResult, - "IssuerValidationResult1", - "IssuerValidationResult2", - null, - context); - } - - internal static bool AreIssuerValidationResultsEqual( - IssuerValidationResult issuerValidationResult1, - IssuerValidationResult issuerValidationResult2, - string name1, - string name2, - string stackPrefix, - CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(issuerValidationResult1, issuerValidationResult2, localContext)) - return context.Merge(localContext); - - if (issuerValidationResult1.Issuer != issuerValidationResult2.Issuer) - localContext.Diffs.Add($"IssuerValidationResult1.Issuer: {issuerValidationResult1.Issuer} != IssuerValidationResult2.Issuer: {issuerValidationResult2.Issuer}"); - - if (issuerValidationResult1.IsValid != issuerValidationResult2.IsValid) - localContext.Diffs.Add($"IssuerValidationResult1.IsValid: {issuerValidationResult1.IsValid} != IssuerValidationResult2.IsValid: {issuerValidationResult2.IsValid}"); - - if (issuerValidationResult1.Source != issuerValidationResult2.Source) - localContext.Diffs.Add($"IssuerValidationResult1.Source: {issuerValidationResult1.Source} != IssuerValidationResult2.Source: {issuerValidationResult2.Source}"); - - // true => both are not null. - if (ContinueCheckingEquality(issuerValidationResult1.Exception, issuerValidationResult2.Exception, localContext)) - { - AreStringsEqual( - issuerValidationResult1.Exception.Message, - issuerValidationResult2.Exception.Message, - $"({name1})issuerValidationResult1.Exception.Message", - $"({name2})issuerValidationResult1.Exception.Message", - localContext); - - AreStringsEqual( - issuerValidationResult1.Exception.Source, - issuerValidationResult2.Exception.Source, - $"({name1})issuerValidationResult1.Exception.Source", - $"({name2})issuerValidationResult2.Exception.Source", - localContext); - - if (!string.IsNullOrEmpty(stackPrefix)) - AreStringPrefixesEqual( - issuerValidationResult1.Exception.StackTrace.Trim(), - issuerValidationResult2.Exception.StackTrace.Trim(), - $"({name1})issuerValidationResult1.Exception.StackTrace", - $"({name2})issuerValidationResult2.Exception.StackTrace", - stackPrefix.Trim(), - localContext); - } - - return context.Merge(localContext); - } - - public static bool AreAudienceValidationResultsEqual(object object1, object object2, CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(object1, object2, context)) - return context.Merge(localContext); - - return AreAudienceValidationResultsEqual( - object1 as AudienceValidationResult, - object2 as AudienceValidationResult, - "AudienceValidationResult1", - "AudienceValidationResult2", - null, - context); - } - - internal static bool AreAudienceValidationResultsEqual( - AudienceValidationResult audienceValidationResult1, - AudienceValidationResult audienceValidationResult2, - string name1, - string name2, - string stackPrefix, - CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(audienceValidationResult1, audienceValidationResult2, localContext)) - return context.Merge(localContext); - - if (audienceValidationResult1.Audience != audienceValidationResult2.Audience) - localContext.Diffs.Add($"AudienceValidationResult1.Audience: '{audienceValidationResult1.Audience}' != AudienceValidationResult2.Audience: '{audienceValidationResult2.Audience}'"); - - if (audienceValidationResult1.IsValid != audienceValidationResult2.IsValid) - localContext.Diffs.Add($"AudienceValidationResult1.IsValid: {audienceValidationResult1.IsValid} != AudienceValidationResult2.IsValid: {audienceValidationResult2.IsValid}"); - - // true => both are not null. - if (ContinueCheckingEquality(audienceValidationResult1.Exception, audienceValidationResult2.Exception, localContext)) - { - AreStringsEqual( - audienceValidationResult1.Exception.Message, - audienceValidationResult2.Exception.Message, - $"({name1})audienceValidationResult1.Exception.Message", - $"({name2})audienceValidationResult2.Exception.Message", - localContext); - - AreStringsEqual( - audienceValidationResult1.Exception.Source, - audienceValidationResult2.Exception.Source, - $"({name1})audienceValidationResult1.Exception.Source", - $"({name2})audienceValidationResult2.Exception.Source", - localContext); - - if (!string.IsNullOrEmpty(stackPrefix)) - AreStringPrefixesEqual( - audienceValidationResult1.Exception.StackTrace.Trim(), - audienceValidationResult2.Exception.StackTrace.Trim(), - $"({name1})audienceValidationResult1.Exception.StackTrace", - $"({name2})audienceValidationResult2.Exception.StackTrace", - stackPrefix.Trim(), - localContext); - } - - return context.Merge(localContext); - } - - public static bool AreSigningKeyValidationResultsEqual(object object1, object object2, CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(object1, object2, context)) - return context.Merge(localContext); - - return AreSigningKeyValidationResultsEqual( - object1 as SigningKeyValidationResult, - object2 as SigningKeyValidationResult, - "SigningKeyValidationResult1", - "SigningKeyValidationResult2", - null, - context); - } - - internal static bool AreSigningKeyValidationResultsEqual( - SigningKeyValidationResult signingKeyValidationResult1, - SigningKeyValidationResult signingKeyValidationResult2, - string name1, - string name2, - string stackPrefix, - CompareContext context) - { - var localContext = new CompareContext(context); - AreSecurityKeysEqual(signingKeyValidationResult1.SigningKey, signingKeyValidationResult2.SigningKey, localContext); - - if (!ContinueCheckingEquality(signingKeyValidationResult1, signingKeyValidationResult2, localContext)) - return context.Merge(localContext); - - if (signingKeyValidationResult1.IsValid != signingKeyValidationResult2.IsValid) - localContext.Diffs.Add($"SigningKeyValidationResult1.IsValid: {signingKeyValidationResult2.IsValid} != SigningKeyValidationResult2.IsValid: {signingKeyValidationResult2.IsValid}"); - - if (signingKeyValidationResult1.ValidationFailureType != signingKeyValidationResult2.ValidationFailureType) - localContext.Diffs.Add($"SigningKeyValidationResult1.ValidationFailureType: {signingKeyValidationResult1.ValidationFailureType} != SigningKeyValidationResult2.ValidationFailureType: {signingKeyValidationResult2.ValidationFailureType}"); - - // true => both are not null. - if (ContinueCheckingEquality(signingKeyValidationResult1.Exception, signingKeyValidationResult2.Exception, localContext)) - { - AreStringsEqual( - signingKeyValidationResult1.Exception.Message, - signingKeyValidationResult2.Exception.Message, - $"({name1})signingKeyValidationResult1.Exception.Message", - $"({name2})signingKeyValidationResult2.Exception.Message", - localContext); - - AreStringsEqual( - signingKeyValidationResult1.Exception.Source, - signingKeyValidationResult2.Exception.Source, - $"({name1})signingKeyValidationResult1.Exception.Source", - $"({name2})signingKeyValidationResult2.Exception.Source", - localContext); - - if (!string.IsNullOrEmpty(stackPrefix)) - AreStringPrefixesEqual( - signingKeyValidationResult1.Exception.StackTrace.Trim(), - signingKeyValidationResult2.Exception.StackTrace.Trim(), - $"({name1})signingKeyValidationResult1.Exception.StackTrace", - $"({name2})signingKeyValidationResult2.Exception.StackTrace", - stackPrefix.Trim(), - localContext); - } - - return context.Merge(localContext); - } - - public static bool AreLifetimeValidationResultsEqual(object object1, object object2, CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(object1, object2, context)) - return context.Merge(localContext); - - return AreLifetimeValidationResultsEqual( - object1 as LifetimeValidationResult, - object2 as LifetimeValidationResult, - "LifetimeValidationResult1", - "LifetimeValidationResult2", - null, - context); - } - - internal static bool AreLifetimeValidationResultsEqual( - LifetimeValidationResult lifetimeValidationResult1, - LifetimeValidationResult lifetimeValidationResult2, - string name1, - string name2, - string stackPrefix, - CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(lifetimeValidationResult1, lifetimeValidationResult2, localContext)) - return context.Merge(localContext); - - if (!AreDatesEqualWithEpsilon(lifetimeValidationResult1.NotBefore, lifetimeValidationResult2.NotBefore, 1)) - localContext.Diffs.Add($"LifetimeValidationResult1.NotBefore: '{lifetimeValidationResult1.NotBefore}' != LifetimeValidationResult2.NotBefore: '{lifetimeValidationResult2.NotBefore}'"); - - if (!AreDatesEqualWithEpsilon(lifetimeValidationResult1.Expires, lifetimeValidationResult2.Expires, 1)) - localContext.Diffs.Add($"LifetimeValidationResult1.Expires: '{lifetimeValidationResult1.Expires}' != LifetimeValidationResult2.Expires: '{lifetimeValidationResult2.Expires}'"); - - if (lifetimeValidationResult1.IsValid != lifetimeValidationResult2.IsValid) - localContext.Diffs.Add($"LifetimeValidationResult1.IsValid: {lifetimeValidationResult1.IsValid} != LifetimeValidationResult2.IsValid: {lifetimeValidationResult2.IsValid}"); - - if (lifetimeValidationResult1.ValidationFailureType != lifetimeValidationResult2.ValidationFailureType) - localContext.Diffs.Add($"LifetimeValidationResult1.ValidationFailureType: {lifetimeValidationResult1.ValidationFailureType} != LifetimeValidationResult2.ValidationFailureType: {lifetimeValidationResult2.ValidationFailureType}"); - - // true => both are not null. - if (ContinueCheckingEquality(lifetimeValidationResult1.Exception, lifetimeValidationResult2.Exception, localContext)) - { - AreStringsEqual( - lifetimeValidationResult1.Exception.Message, - lifetimeValidationResult2.Exception.Message, - $"({name1})lifetimeValidationResult1.Exception.Message", - $"({name2})lifetimeValidationResult2.Exception.Message", - localContext); - - AreStringsEqual( - lifetimeValidationResult1.Exception.Source, - lifetimeValidationResult2.Exception.Source, - $"({name1})lifetimeValidationResult1.Exception.Source", - $"({name2})lifetimeValidationResult2.Exception.Source", - localContext); - - if (!string.IsNullOrEmpty(stackPrefix)) - AreStringPrefixesEqual( - lifetimeValidationResult1.Exception.StackTrace.Trim(), - lifetimeValidationResult2.Exception.StackTrace.Trim(), - $"({name1})lifetimeValidationResult1.Exception.StackTrace", - $"({name2})lifetimeValidationResult2.Exception.StackTrace", - stackPrefix.Trim(), - localContext); - } - - return context.Merge(localContext); - } - - public static bool AreTokenReplayValidationResultsEqual(object object1, object object2, CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(object1, object2, context)) - return context.Merge(localContext); - - return AreTokenReplayValidationResultsEqual( - object1 as ReplayValidationResult, - object2 as ReplayValidationResult, - "ReplayValidationResult1", - "ReplayValidationResult2", - null, - context); - } - - internal static bool AreTokenReplayValidationResultsEqual( - ReplayValidationResult replayValidationResult1, - ReplayValidationResult replayValidationResult2, - string name1, - string name2, - string stackPrefix, - CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(replayValidationResult1, replayValidationResult2, localContext)) - return context.Merge(localContext); - - if (replayValidationResult1.ExpirationTime != replayValidationResult2.ExpirationTime) - localContext.Diffs.Add($"ReplayValidationResult1.ExpirationTime: '{replayValidationResult1.ExpirationTime}' != ReplayValidationResult2.ExpirationTime: '{replayValidationResult2.ExpirationTime}'"); - - if (replayValidationResult1.IsValid != replayValidationResult2.IsValid) - localContext.Diffs.Add($"ReplayValidationResult1.IsValid: {replayValidationResult1.IsValid} != ReplayValidationResult2.IsValid: {replayValidationResult2.IsValid}"); - - if (replayValidationResult1.ValidationFailureType != replayValidationResult2.ValidationFailureType) - localContext.Diffs.Add($"ReplayValidationResult1.ValidationFailureType: {replayValidationResult1.ValidationFailureType} != ReplayValidationResult2.ValidationFailureType: {replayValidationResult2.ValidationFailureType}"); - - // true => both are not null. - if (ContinueCheckingEquality(replayValidationResult1.Exception, replayValidationResult2.Exception, localContext)) - { - AreStringsEqual( - replayValidationResult1.Exception.Message, - replayValidationResult2.Exception.Message, - $"({name1}).Exception.Message", - $"({name2}).Exception.Message", - localContext); - - AreStringsEqual( - replayValidationResult1.Exception.Source, - replayValidationResult2.Exception.Source, - $"({name1}).Exception.Source", - $"({name2}).Exception.Source", - localContext); - - if (!string.IsNullOrEmpty(stackPrefix)) - AreStringPrefixesEqual( - replayValidationResult1.Exception.StackTrace.Trim(), - replayValidationResult2.Exception.StackTrace.Trim(), - $"({name1}).Exception.StackTrace", - $"({name2}).Exception.StackTrace", - stackPrefix.Trim(), - localContext); - } - - return context.Merge(localContext); - } - - public static bool AreTokenTypeValidationResultsEqual(object object1, object object2, CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(object1, object2, context)) - return context.Merge(localContext); - - return AreTokenTypeValidationResultsEqual( - object1 as TokenTypeValidationResult, - object2 as TokenTypeValidationResult, - "TokenTypeValidationResult1", - "TokenTypeValidationResult2", - null, - context); - } - - internal static bool AreTokenTypeValidationResultsEqual( - TokenTypeValidationResult tokenTypeValidationResult1, - TokenTypeValidationResult tokenTypeValidationResult2, - string name1, - string name2, - string stackPrefix, - CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(tokenTypeValidationResult1, tokenTypeValidationResult2, localContext)) - return context.Merge(localContext); - - if (tokenTypeValidationResult1.Type != tokenTypeValidationResult2.Type) - localContext.Diffs.Add($"TokenTypeValidationResult1.Type: '{tokenTypeValidationResult1.Type}' != TokenTypeValidationResult2.Type: '{tokenTypeValidationResult2.Type}'"); - - if (tokenTypeValidationResult1.IsValid != tokenTypeValidationResult2.IsValid) - localContext.Diffs.Add($"TokenTypeValidationResult1.IsValid: {tokenTypeValidationResult1.IsValid} != TokenTypeValidationResult2.IsValid: {tokenTypeValidationResult2.IsValid}"); - - if (tokenTypeValidationResult1.ValidationFailureType != tokenTypeValidationResult2.ValidationFailureType) - localContext.Diffs.Add($"TokenTypeValidationResult1.ValidationFailureType: {tokenTypeValidationResult1.ValidationFailureType} != TokenTypeValidationResult2.ValidationFailureType: {tokenTypeValidationResult2.ValidationFailureType}"); - - // true => both are not null. - if (ContinueCheckingEquality(tokenTypeValidationResult1.Exception, tokenTypeValidationResult2.Exception, localContext)) - { - AreStringsEqual( - tokenTypeValidationResult1.Exception.Message, - tokenTypeValidationResult2.Exception.Message, - $"({name1}).Exception.Message", - $"({name2}).Exception.Message", - localContext); - - AreStringsEqual( - tokenTypeValidationResult1.Exception.Source, - tokenTypeValidationResult2.Exception.Source, - $"({name1}).Exception.Source", - $"({name2}).Exception.Source", - localContext); - - if (!string.IsNullOrEmpty(stackPrefix)) - AreStringPrefixesEqual( - tokenTypeValidationResult1.Exception.StackTrace.Trim(), - tokenTypeValidationResult2.Exception.StackTrace.Trim(), - $"({name1}).Exception.StackTrace", - $"({name2}).Exception.StackTrace", - stackPrefix.Trim(), - localContext); - } - - return context.Merge(localContext); - } - - public static bool AreTokenReadingResultsEqual(object object1, object object2, CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(object1, object2, context)) - return context.Merge(localContext); - - return AreTokenReadingResultsEqual( - object1 as TokenReadingResult, - object2 as TokenReadingResult, - "TokenReadingResult1", - "TokenReadingResult2", - null, - context); - } - - internal static bool AreTokenReadingResultsEqual( - TokenReadingResult tokenReadingResult1, - TokenReadingResult tokenReadingResult2, - string name1, - string name2, - string stackPrefix, - CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(tokenReadingResult1, tokenReadingResult2, localContext)) - return context.Merge(localContext); - - if (tokenReadingResult1.IsValid != tokenReadingResult2.IsValid) - localContext.Diffs.Add($"TokenReadingResult1.IsValid: {tokenReadingResult1.IsValid} != TokenReadingResult2.IsValid: {tokenReadingResult2.IsValid}"); - - if (tokenReadingResult1.TokenInput != tokenReadingResult2.TokenInput) - localContext.Diffs.Add($"TokenReadingResult1.TokenInput: '{tokenReadingResult1.TokenInput}' != TokenReadingResult2.TokenInput: '{tokenReadingResult2.TokenInput}'"); - - // Only compare the security token if both are valid. - if (tokenReadingResult1.IsValid && (tokenReadingResult1.SecurityToken().ToString() != tokenReadingResult2.SecurityToken().ToString())) - localContext.Diffs.Add($"TokenReadingResult1.SecurityToken: '{tokenReadingResult1.SecurityToken()}' != TokenReadingResult2.SecurityToken: '{tokenReadingResult2.SecurityToken()}'"); - - if (tokenReadingResult1.ValidationFailureType != tokenReadingResult2.ValidationFailureType) - localContext.Diffs.Add($"TokenReadingResult1.ValidationFailureType: {tokenReadingResult1.ValidationFailureType} != TokenReadingResult2.ValidationFailureType: {tokenReadingResult2.ValidationFailureType}"); - - // true => both are not null. - if (ContinueCheckingEquality(tokenReadingResult1.Exception, tokenReadingResult2.Exception, localContext)) - { - AreStringsEqual( - tokenReadingResult1.Exception.Message, - tokenReadingResult2.Exception.Message, - $"({name1}).Exception.Message", - $"({name2}).Exception.Message", - localContext); - - AreStringsEqual( - tokenReadingResult1.Exception.Source, - tokenReadingResult2.Exception.Source, - $"({name1}).Exception.Source", - $"({name2}).Exception.Source", - localContext); - - if (!string.IsNullOrEmpty(stackPrefix)) - AreStringPrefixesEqual( - tokenReadingResult1.Exception.StackTrace.Trim(), - tokenReadingResult2.Exception.StackTrace.Trim(), - $"({name1}).Exception.StackTrace", - $"({name2}).Exception.StackTrace", - stackPrefix.Trim(), - localContext); - } - - return context.Merge(localContext); - } - - public static bool AreTokenDecryptingResultsEqual(object object1, object object2, CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(object1, object2, context)) - return context.Merge(localContext); - - return AreTokenDecryptingResultsEqual( - object1 as TokenDecryptionResult, - object2 as TokenDecryptionResult, - "TokenDecryptingResult1", - "TokenDecryptingResult2", - null, - context); - } - - internal static bool AreTokenDecryptingResultsEqual( - TokenDecryptionResult tokenDecryptingResult1, - TokenDecryptionResult tokenDecryptingResult2, - string name1, - string name2, - string stackPrefix, - CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(tokenDecryptingResult1, tokenDecryptingResult2, localContext)) - return context.Merge(localContext); - - if (tokenDecryptingResult1.IsValid != tokenDecryptingResult2.IsValid) - localContext.Diffs.Add($"TokenDecryptingResult1.IsValid: {tokenDecryptingResult1.IsValid} != TokenDecryptingResult2.IsValid: {tokenDecryptingResult2.IsValid}"); - - if (tokenDecryptingResult1.SecurityToken == null || tokenDecryptingResult2.SecurityToken == null) - { - if (tokenDecryptingResult1.SecurityToken != tokenDecryptingResult2.SecurityToken) - localContext.Diffs.Add($"TokenDecryptingResult1.SecurityToken: '{tokenDecryptingResult1.SecurityToken}' != TokenDecryptingResult2.SecurityToken: '{tokenDecryptingResult2.SecurityToken}'"); - } - else if (tokenDecryptingResult1.SecurityToken.ToString() != tokenDecryptingResult2.SecurityToken.ToString()) - localContext.Diffs.Add($"TokenDecryptingResult1.SecurityToken: '{tokenDecryptingResult1.SecurityToken}' != TokenDecryptingResult2.SecurityToken: '{tokenDecryptingResult2.SecurityToken}'"); - - // Only compare the decrypted token if both results are valid. - if (tokenDecryptingResult1.IsValid && (tokenDecryptingResult1.DecryptedToken().ToString() != tokenDecryptingResult2.DecryptedToken().ToString())) - localContext.Diffs.Add($"TokenDecryptingResult1.DecryptedToken: '{tokenDecryptingResult1.DecryptedToken()}' != TokenDecryptingResult2.DecryptedToken: '{tokenDecryptingResult2.DecryptedToken()}'"); - - if (tokenDecryptingResult1.ValidationFailureType != tokenDecryptingResult2.ValidationFailureType) - localContext.Diffs.Add($"TokenDecryptingResult1.ValidationFailureType: {tokenDecryptingResult1.ValidationFailureType} != TokenDecryptingResult1.ValidationFailureType: {tokenDecryptingResult2.ValidationFailureType}"); - - // true => both are not null. - if (ContinueCheckingEquality(tokenDecryptingResult1.Exception, tokenDecryptingResult2.Exception, localContext)) - { - AreStringsEqual( - tokenDecryptingResult1.Exception.Message, - tokenDecryptingResult2.Exception.Message, - $"({name1}).Exception.Message", - $"({name2}).Exception.Message", - localContext); - - AreStringsEqual( - tokenDecryptingResult1.Exception.Source, - tokenDecryptingResult2.Exception.Source, - $"({name1}).Exception.Source", - $"({name2}).Exception.Source", - localContext); - - if (!string.IsNullOrEmpty(stackPrefix)) - AreStringPrefixesEqual( - tokenDecryptingResult1.Exception.StackTrace.Trim(), - tokenDecryptingResult2.Exception.StackTrace.Trim(), - $"({name1}).Exception.StackTrace", - $"({name2}).Exception.StackTrace", - stackPrefix.Trim(), - localContext); - } - - return context.Merge(localContext); - } - public static bool AreJArraysEqual(object object1, object object2, CompareContext context) { var localContext = new CompareContext(context); @@ -1628,69 +1019,6 @@ public static bool AreSecurityKeyEnumsEqual(object object1, object object2, Comp return AreEnumsEqual(object1 as IEnumerable, object2 as IEnumerable, context, AreSecurityKeysEqual); } - public static bool AreSignatureValidationResultsEqual(object object1, object object2, CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(object1, object2, context)) - return context.Merge(localContext); - - return AreSignatureValidationResultsEqual( - object1 as SignatureValidationResult, - object2 as SignatureValidationResult, - "SignatureValidationResult1", - "SignatureValidationResult2", - null, - context); - } - - internal static bool AreSignatureValidationResultsEqual( - SignatureValidationResult signatureValidationResult1, - SignatureValidationResult signatureValidationResult2, - string name1, - string name2, - string stackPrefix, - CompareContext context) - { - var localContext = new CompareContext(context); - if (!ContinueCheckingEquality(signatureValidationResult1, signatureValidationResult2, localContext)) - return context.Merge(localContext); - - if (signatureValidationResult1.IsValid != signatureValidationResult2.IsValid) - localContext.Diffs.Add($"{name1}.IsValid: {signatureValidationResult1.IsValid} != {name2}.IsValid: {signatureValidationResult2.IsValid}"); - - if (signatureValidationResult1.ValidationFailureType != signatureValidationResult2.ValidationFailureType) - localContext.Diffs.Add($"{name1}.IsValid: {signatureValidationResult1.ValidationFailureType} != {name2}.IsValid: {signatureValidationResult2.ValidationFailureType}"); - - // true => both are not null. - if (ContinueCheckingEquality(signatureValidationResult1.Exception, signatureValidationResult2.Exception, localContext)) - { - AreStringsEqual( - signatureValidationResult1.Exception.Message, - signatureValidationResult2.Exception.Message, - $"({name1}).Exception.Message", - $"({name2}).Exception.Message", - localContext); - - AreStringsEqual( - signatureValidationResult1.Exception.Source, - signatureValidationResult2.Exception.Source, - $"({name1}).Exception.Source", - $"({name2}).Exception.Source", - localContext); - - if (!string.IsNullOrEmpty(stackPrefix)) - AreStringPrefixesEqual( - signatureValidationResult1.Exception.StackTrace.Trim(), - signatureValidationResult2.Exception.StackTrace.Trim(), - $"({name1}).Exception.StackTrace", - $"({name2}).Exception.StackTrace", - stackPrefix.Trim(), - localContext); - } - - return context.Merge(localContext); - } - public static bool AreSignedInfosEqual(SignedInfo signedInfo1, SignedInfo signedInfo2, CompareContext context) { var localContext = new CompareContext(context); @@ -1885,6 +1213,23 @@ public static bool AreTimeSpansEqual(object object1, object object2, CompareCont return context.Merge(localContext); } + internal static bool AreTokenValidationErrorsEqual(ITokenValidationError tokenValidationError1, ITokenValidationError tokenValidationError2, CompareContext context) + { + var localContext = new CompareContext(context); + + AreIntsEqual( + tokenValidationError1.ErrorType, + tokenValidationError2.ErrorType, + localContext); + + AreStringsEqual( + tokenValidationError1.MessageDetail.Message, + tokenValidationError2.MessageDetail.Message, + localContext); + + return context.Merge(localContext); + } + private static bool AreValueCollectionsEqual(Object object1, Object object2, CompareContext context) { Dictionary.ValueCollection vc1 = (Dictionary.ValueCollection)object1; diff --git a/test/Microsoft.IdentityModel.TestUtils/InternalsVisibleTo.cs b/test/Microsoft.IdentityModel.TestUtils/InternalsVisibleTo.cs new file mode 100644 index 0000000000..84597b7355 --- /dev/null +++ b/test/Microsoft.IdentityModel.TestUtils/InternalsVisibleTo.cs @@ -0,0 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.JsonWebTokens.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.Tokens.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs index 3308c7771c..9ffc5a59df 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs @@ -1,11 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System; -using System.Diagnostics; using Microsoft.IdentityModel.TestUtils; using Microsoft.IdentityModel.Logging; using Xunit; +using Microsoft.IdentityModel.Abstractions; namespace Microsoft.IdentityModel.Tokens.Validation.Tests { @@ -16,22 +15,30 @@ public void ValidateAlgorithm(AlgorithmTheoryData theoryData) { CompareContext context = TestUtilities.WriteHeader($"{this}.AlgorithmValidationResultTests", theoryData); - AlgorithmValidationResult algorithmValidationResult = Validators.ValidateAlgorithm( + Result result = Validators.ValidateAlgorithm( theoryData.Algorithm, theoryData.SecurityKey, theoryData.SecurityToken, theoryData.ValidationParameters, new CallContext()); - if (algorithmValidationResult.Exception != null) - theoryData.ExpectedException.ProcessException(algorithmValidationResult.Exception); + if (result.IsSuccess) + IdentityComparer.AreStringsEqual( + result.UnwrapResult(), + theoryData.Result.UnwrapResult(), + context); else - theoryData.ExpectedException.ProcessNoException(); + { + IdentityComparer.AreTokenValidationErrorsEqual( + result.UnwrapError(), + theoryData.Result.UnwrapError(), + context); - IdentityComparer.AreAlgorithmValidationResultsEqual( - algorithmValidationResult, - theoryData.AlgorithmValidationResult, - context); + if (result.UnwrapError().InnerException is not null) + theoryData.ExpectedException.ProcessException(result.UnwrapError().InnerException); + else + theoryData.ExpectedException.ProcessNoException(); + } TestUtilities.AssertFailIfErrors(context); } @@ -47,24 +54,20 @@ public static TheoryData AlgorithmValidationTestCases new AlgorithmTheoryData { TestId = "Invalid_ValidationParametersAreNull", - ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), Algorithm = null, SecurityKey = null, SecurityToken = null, ValidationParameters = null, - AlgorithmValidationResult = new AlgorithmValidationResult( - null, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII("validationParameters")), - ExceptionDetail.ExceptionType.ArgumentNull)) + Result = new TokenValidationError( + ValidationErrorType.ArgumentNull, + new MessageDetail( + LogMessages.IDX10000, + LogHelper.MarkAsNonPII("validationParameters")), + null) }, new AlgorithmTheoryData { TestId = "Invalid_ValidateAlgorithmNotAValidAlgorithm", - ExpectedException = ExpectedException.SecurityTokenInvalidAlgorithmException("IDX10696:"), Algorithm = SecurityAlgorithms.Sha256, SecurityKey = securityKey, SecurityToken = null, @@ -72,15 +75,12 @@ public static TheoryData AlgorithmValidationTestCases { ValidAlgorithms = new[] { SecurityAlgorithms.HmacSha256 } }, - AlgorithmValidationResult = new AlgorithmValidationResult( - SecurityAlgorithms.Sha256, - ValidationFailureType.AlgorithmValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10696, - LogHelper.MarkAsNonPII(SecurityAlgorithms.Sha256), - securityKey), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAlgorithm)) + Result = new TokenValidationError( + ValidationErrorType.ArgumentNull, + new MessageDetail( + LogMessages.IDX10696, + LogHelper.MarkAsNonPII(SecurityAlgorithms.Sha256)), + null), }, new AlgorithmTheoryData { @@ -92,7 +92,7 @@ public static TheoryData AlgorithmValidationTestCases { ValidAlgorithms = null }, - AlgorithmValidationResult = new AlgorithmValidationResult(SecurityAlgorithms.Sha256) + Result = SecurityAlgorithms.Sha256 }, new AlgorithmTheoryData { @@ -104,7 +104,7 @@ public static TheoryData AlgorithmValidationTestCases { ValidAlgorithms = new[] { SecurityAlgorithms.HmacSha256, SecurityAlgorithms.Sha256 } }, - AlgorithmValidationResult = new AlgorithmValidationResult(SecurityAlgorithms.Sha256) + Result = SecurityAlgorithms.Sha256 } }; } @@ -120,7 +120,7 @@ public class AlgorithmTheoryData : TheoryDataBase internal ValidationParameters ValidationParameters { get; set; } - internal AlgorithmValidationResult AlgorithmValidationResult { get; set; } + internal Result Result { get; set; } } } } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs index 61d31ea072..0d1676b94c 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs @@ -8,12 +8,13 @@ using Microsoft.IdentityModel.Tokens.Json.Tests; using Xunit; using System.Collections.Generic; +using Microsoft.IdentityModel.Abstractions; namespace Microsoft.IdentityModel.Tokens.Validation.Tests { public class AudienceValidationResultTests { - [Theory, MemberData(nameof(ValidateAudienceParametersTestCases), DisableDiscoveryEnumeration = true)] + [Theory, MemberData(nameof(ValidateAudienceTestCases), DisableDiscoveryEnumeration = true)] public void ValidateAudienceParameters(AudienceValidationTheoryData theoryData) { CompareContext context = TestUtilities.WriteHeader($"{this}.AudienceValidatorResultTests", theoryData); @@ -24,460 +25,341 @@ public void ValidateAudienceParameters(AudienceValidationTheoryData theoryData) theoryData.ValidationParameters.ValidAudiences.Add(audience); } - AudienceValidationResult audienceValidationResult = Validators.ValidateAudience( + Result result = Validators.ValidateAudience( theoryData.Audiences, theoryData.SecurityToken, theoryData.ValidationParameters, new CallContext()); - if (audienceValidationResult.Exception == null) - theoryData.ExpectedException.ProcessNoException(); + if (result.IsSuccess) + IdentityComparer.AreStringsEqual( + result.UnwrapResult(), + theoryData.Result.UnwrapResult(), + context); else - theoryData.ExpectedException.ProcessException(audienceValidationResult.Exception, context); + { + IdentityComparer.AreTokenValidationErrorsEqual( + result.UnwrapError(), + theoryData.Result.UnwrapError(), + context); - IdentityComparer.AreAudienceValidationResultsEqual( - audienceValidationResult, - theoryData.AudienceValidationResult, - context); + if (result.UnwrapError().InnerException is not null) + theoryData.ExpectedException.ProcessException(result.UnwrapError().InnerException); + else + theoryData.ExpectedException.ProcessNoException(); - TestUtilities.AssertFailIfErrors(context); + TestUtilities.AssertFailIfErrors(context); + } } - public static TheoryData ValidateAudienceParametersTestCases + public static TheoryData ValidateAudienceTestCases { get { + var audience1 = "http://audience1.com"; + var audience2 = "http://audience2.com"; + List audiences1 = new List { "", audience1 }; + List audiences1WithSlash = new List { "", audience1 + "/" }; + List audiences1WithTwoSlashes = new List { "", audience1 + "//" }; + List audiences2 = new List { "", audience2 }; + List audiences2WithSlash = new List { "", audience2 + "/" }; + + var commaAudience1 = ", " + audience1; + var commaAudience2 = ", " + audience2; + var audience1Slash = audience1 + "/"; + var audience2Slash = audience2 + "/"; + var commaAudience1Slash = commaAudience1 + "/"; + var commaAudience2Slash = commaAudience2 + "/"; + return new TheoryData { new AudienceValidationTheoryData { Audiences = new List { "audience1" }, - ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), - TestId = "ValidationParametersNull", + TestId = "Invalid_ValidationParametersIsNull", ValidationParameters = null, - AudienceValidationResult = new AudienceValidationResult( - "audience1", - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII("validationParameters")), - ExceptionDetail.ExceptionType.ArgumentNull, - null)), + Result = new TokenValidationError( + ValidationErrorType.ArgumentNull, + new MessageDetail( + LogMessages.IDX10000, + LogHelper.MarkAsNonPII("validationParameters")), + null) }, new AudienceValidationTheoryData { Audiences = null, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10207:"), - TestId = "AudiencesNull", - AudienceValidationResult = new AudienceValidationResult( - "null", - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10207, - null), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - null)), + TestId = "Invalid_AudiencesIsNull", + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10207, + null), + null) }, new AudienceValidationTheoryData { Audiences = new List{ }, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10206:"), - TestId = "AudiencesEmptyList", + TestId = "Invalid_AudiencesIsEmptyList", ValidationParameters = new ValidationParameters(), - AudienceValidationResult = new AudienceValidationResult( - "empty", - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10206, - null), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10206, + null), + null) }, new AudienceValidationTheoryData { Audiences = new List { "audience1" }, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), - TestId = "ValidAudiencesEmptyString", + TestId = "Invalid_ValidAudiencesIsEmptyString", ValidationParameters = new ValidationParameters(), AudiencesToAdd = [String.Empty], - AudienceValidationResult = new AudienceValidationResult( - "audience1", - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10215, - LogHelper.MarkAsNonPII("audience1"), - LogHelper.MarkAsNonPII(String.Empty)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10215, + LogHelper.MarkAsNonPII("audience1"), + LogHelper.MarkAsNonPII(String.Empty)), + null) }, new AudienceValidationTheoryData { Audiences = new List { "audience1" }, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), - TestId = "ValidAudiencesWhiteSpace", + TestId = "Invalid_ValidAudiencesIsWhiteSpace", ValidationParameters = new ValidationParameters(), AudiencesToAdd = [" "], - AudienceValidationResult = new AudienceValidationResult( - "audience1", - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10215, - LogHelper.MarkAsNonPII("audience1"), - LogHelper.MarkAsNonPII(" ")), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - - null)), - } - }; - } - } - - [Theory, MemberData(nameof(ValidateAudienceTheoryData))] - public void ValidateAudience(AudienceValidationTheoryData theoryData) - { - var context = TestUtilities.WriteHeader($"{this}.ValidateAudience", theoryData); - - if (theoryData.AudiencesToAdd != null) - { - foreach (string audience in theoryData.AudiencesToAdd) - theoryData.ValidationParameters.ValidAudiences.Add(audience); - } - - AudienceValidationResult audienceValidationResult = Validators.ValidateAudience( - theoryData.Audiences, - theoryData.SecurityToken, - theoryData.ValidationParameters, - new CallContext()); - - if (audienceValidationResult.Exception != null) - theoryData.ExpectedException.ProcessException(audienceValidationResult.Exception); - else - theoryData.ExpectedException.ProcessNoException(context); - - IdentityComparer.AreAudienceValidationResultsEqual( - audienceValidationResult, - theoryData.AudienceValidationResult, - context); - - TestUtilities.AssertFailIfErrors(context); - } - - public static TheoryData ValidateAudienceTheoryData - { - get - { - var audience1 = "http://audience1.com"; - var audience2 = "http://audience2.com"; - List audiences1 = new List { "", audience1 }; - List audiences1WithSlash = new List { "", audience1 + "/" }; - List audiences1WithTwoSlashes = new List { "", audience1 + "//" }; - List audiences2 = new List { "", audience2 }; - List audiences2WithSlash = new List { "", audience2 + "/" }; - - var commaAudience1 = ", " + audience1; - var commaAudience2 = ", " + audience2; - var audience1Slash = audience1 + "/"; - var audience2Slash = audience2 + "/"; - var commaAudience1Slash = commaAudience1 + "/"; - var commaAudience2Slash = commaAudience2 + "/"; - - return new TheoryData - { + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10215, + LogHelper.MarkAsNonPII("audience1"), + LogHelper.MarkAsNonPII(" ")), + null) + }, new AudienceValidationTheoryData { Audiences = audiences1, - TestId = "SameLengthMatched", + TestId = "Valid_SameLengthMatched", ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience1], SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, "Issuer"), - AudienceValidationResult = new AudienceValidationResult(audience1) + Result = audience1 }, new AudienceValidationTheoryData { Audiences = audiences1, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), - TestId = "SameLengthNotMatched", + TestId = "Invalid_SameLengthNotMatched", ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience2], SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, "Issuer"), - AudienceValidationResult = new AudienceValidationResult( - commaAudience1, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10215, - LogHelper.MarkAsNonPII(commaAudience1), - LogHelper.MarkAsNonPII(audience2)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10215, + LogHelper.MarkAsNonPII(commaAudience1), + LogHelper.MarkAsNonPII(audience2)), + null) }, new AudienceValidationTheoryData { Audiences = audiences1, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), - TestId = "AudiencesValidAudienceWithSlashNotMatched", + TestId = "Invalid_AudiencesValidAudienceWithSlashNotMatched", ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience2 + "/"], SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, "Issuer"), - AudienceValidationResult = new AudienceValidationResult( - commaAudience1, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10215, - LogHelper.MarkAsNonPII(commaAudience1), - LogHelper.MarkAsNonPII(audience2Slash)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10215, + LogHelper.MarkAsNonPII(commaAudience1), + LogHelper.MarkAsNonPII(audience2Slash)), + null) }, new AudienceValidationTheoryData { Audiences = audiences2WithSlash, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), - TestId = "AudiencesWithSlashValidAudienceSameLengthNotMatched", + TestId = "Invalid_AudiencesWithSlashValidAudienceSameLengthNotMatched", ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience1], - AudienceValidationResult = new AudienceValidationResult( - commaAudience2Slash, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10215, - LogHelper.MarkAsNonPII(commaAudience2Slash), - LogHelper.MarkAsNonPII(audience1)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10215, + LogHelper.MarkAsNonPII(commaAudience2Slash), + LogHelper.MarkAsNonPII(audience1)), + null) }, new AudienceValidationTheoryData { Audiences = audiences1, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), - TestId = "ValidAudienceWithSlashVPFalse", + TestId = "Invalid_ValidAudienceWithSlash_IgnoreTrailingSlashFalse", ValidationParameters = new ValidationParameters{ IgnoreTrailingSlashWhenValidatingAudience = false }, AudiencesToAdd = [audience1 + "/"], - AudienceValidationResult = new AudienceValidationResult( - commaAudience1, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10215, - LogHelper.MarkAsNonPII(commaAudience1), - LogHelper.MarkAsNonPII(audience1Slash)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10215, + LogHelper.MarkAsNonPII(commaAudience1), + LogHelper.MarkAsNonPII(audience1Slash)), + null) }, new AudienceValidationTheoryData { Audiences = audiences1, - TestId = "ValidAudienceWithSlashVPTrue", + TestId = "Valid_ValidAudienceWithSlash_IgnoreTrailingSlashTrue", ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience1 + "/"], - AudienceValidationResult = new AudienceValidationResult(audience1) + Result = audience1 }, new AudienceValidationTheoryData { Audiences = audiences1, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), - TestId = "ValidAudiencesWithSlashVPFalse", + TestId = "Invalid_ValidAudiencesWithSlash_IgnoreTrailingSlashFalse", ValidationParameters = new ValidationParameters{ IgnoreTrailingSlashWhenValidatingAudience = false }, AudiencesToAdd = audiences1WithSlash, - AudienceValidationResult = new AudienceValidationResult( - commaAudience1, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10215, - LogHelper.MarkAsNonPII(commaAudience1), - LogHelper.MarkAsNonPII(commaAudience1Slash)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10215, + LogHelper.MarkAsNonPII(commaAudience1), + LogHelper.MarkAsNonPII(commaAudience1Slash)), + null) }, new AudienceValidationTheoryData { Audiences = audiences1, - TestId = "ValidAudiencesWithSlashVPTrue", + TestId = "Valid_ValidAudiencesWithSlash_IgnoreTrailingSlashTrue", ValidationParameters = new ValidationParameters(), AudiencesToAdd = audiences1WithSlash, - AudienceValidationResult = new AudienceValidationResult(audience1) + Result = audience1 }, new AudienceValidationTheoryData { Audiences = audiences1, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), - TestId = "ValidAudienceWithExtraChar", + TestId = "Invalid_ValidAudienceWithExtraChar", ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience1 + "A"], - AudienceValidationResult = new AudienceValidationResult( - commaAudience1, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10215, - LogHelper.MarkAsNonPII(commaAudience1), - LogHelper.MarkAsNonPII(audience1 + "A")), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10215, + LogHelper.MarkAsNonPII(commaAudience1), + LogHelper.MarkAsNonPII(audience1 + "A")), + null) }, new AudienceValidationTheoryData { Audiences = audiences1, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), - TestId = "ValidAudienceWithDoubleSlashVPTrue", + TestId = "Invalid_ValidAudienceWithDoubleSlash_IgnoreTrailingSlashTrue", ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience1 + "//"], - AudienceValidationResult = new AudienceValidationResult( - commaAudience1, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10215, - LogHelper.MarkAsNonPII(commaAudience1), - LogHelper.MarkAsNonPII(audience1 + "//")), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10215, + LogHelper.MarkAsNonPII(commaAudience1), + LogHelper.MarkAsNonPII(audience1 + "//")), + null) }, new AudienceValidationTheoryData { Audiences = audiences1, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), - TestId = "ValidAudiencesWithDoubleSlashVPTrue", + TestId = "Invalid_ValidAudiencesWithDoubleSlash_IgnoreTrailingSlashTrue", ValidationParameters = new ValidationParameters(), AudiencesToAdd = audiences1WithTwoSlashes, - AudienceValidationResult = new AudienceValidationResult( - commaAudience1, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10215, - LogHelper.MarkAsNonPII(commaAudience1), - LogHelper.MarkAsNonPII(commaAudience1 + "//")), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10215, + LogHelper.MarkAsNonPII(commaAudience1), + LogHelper.MarkAsNonPII(commaAudience1 + "//")), + null) }, new AudienceValidationTheoryData { Audiences = audiences1WithSlash, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), - TestId = "TokenAudienceWithSlashVPFalse", + TestId = "Invalid_TokenAudienceWithSlash_IgnoreTrailingSlashFalse", ValidationParameters = new ValidationParameters{ IgnoreTrailingSlashWhenValidatingAudience = false }, AudiencesToAdd = [audience1], - AudienceValidationResult = new AudienceValidationResult( - commaAudience1Slash, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10215, - LogHelper.MarkAsNonPII(commaAudience1Slash), - LogHelper.MarkAsNonPII(audience1)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10215, + LogHelper.MarkAsNonPII(commaAudience1Slash), + LogHelper.MarkAsNonPII(audience1)), + null) }, new AudienceValidationTheoryData { Audiences = audiences1WithSlash, - TestId = "TokenAudienceWithSlashVPTrue", + TestId = "Valid_TokenAudienceWithSlash_IgnoreTrailingSlashTrue", ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience1], - AudienceValidationResult = new AudienceValidationResult(audience1Slash) + Result = audience1Slash }, new AudienceValidationTheoryData { Audiences = audiences2WithSlash, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), - TestId = "TokenAudienceWithSlashNotEqual", + TestId = "Invalid_TokenAudienceWithSlashNotEqual", ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience1], - AudienceValidationResult = new AudienceValidationResult( - commaAudience2Slash, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10215, - LogHelper.MarkAsNonPII(commaAudience2Slash), - LogHelper.MarkAsNonPII(audience1)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10215, + LogHelper.MarkAsNonPII(commaAudience2Slash), + LogHelper.MarkAsNonPII(audience1)), + null) }, new AudienceValidationTheoryData { Audiences = audiences1WithSlash, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), - TestId = "TokenAudiencesWithSlashVPFalse", + TestId = "Invalid_TokenAudiencesWithSlash_IgnoreTrailingSlashFalse", ValidationParameters = new ValidationParameters{ IgnoreTrailingSlashWhenValidatingAudience = false }, AudiencesToAdd = [audience1], - AudienceValidationResult = new AudienceValidationResult( - commaAudience1Slash, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10215, - LogHelper.MarkAsNonPII(commaAudience1Slash), - LogHelper.MarkAsNonPII(audience1)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10215, + LogHelper.MarkAsNonPII(commaAudience1Slash), + LogHelper.MarkAsNonPII(audience1)), + null) }, new AudienceValidationTheoryData { Audiences = audiences1WithSlash, - TestId = "TokenAudiencesWithSlashVPTrue", + TestId = "Valid_TokenAudiencesWithSlash_IgnoreTrailingSlashTrue", ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience1], - AudienceValidationResult = new AudienceValidationResult(audience1Slash) + Result = audience1Slash }, new AudienceValidationTheoryData { Audiences = audiences1WithSlash, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), - TestId = "TokenAudiencesWithSlashValidAudiencesNotMatchedVPTrue", + TestId = "Invalid_TokenAudiencesWithSlashValidAudiencesNotMatched_IgnoreTrailingSlashTrue", ValidationParameters = new ValidationParameters(), AudiencesToAdd = audiences2, - AudienceValidationResult = new AudienceValidationResult( - commaAudience1Slash, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10215, - LogHelper.MarkAsNonPII(commaAudience1Slash), - LogHelper.MarkAsNonPII(commaAudience2)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10215, + LogHelper.MarkAsNonPII(commaAudience1Slash), + LogHelper.MarkAsNonPII(commaAudience2)), + null) }, new AudienceValidationTheoryData { Audiences = audiences1WithTwoSlashes, - ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), TestId = "TokenAudienceWithTwoSlashesVPTrue", ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience1], - AudienceValidationResult = new AudienceValidationResult( - commaAudience1 + "//", - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10215, - LogHelper.MarkAsNonPII(commaAudience1 + "//"), - LogHelper.MarkAsNonPII(audience1)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, - - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidAudience, + new MessageDetail( + LogMessages.IDX10215, + LogHelper.MarkAsNonPII(commaAudience1 + "//"), + LogHelper.MarkAsNonPII(audience1)), + null) } }; } @@ -487,14 +369,15 @@ public class AudienceValidationTheoryData : TheoryDataBase { public List Audiences { get; set; } - internal AudienceValidationResult AudienceValidationResult { get; set; } - public SecurityToken SecurityToken { get; set; } internal ValidationParameters ValidationParameters { get; set; } = new ValidationParameters(); internal ValidationFailureType ValidationFailureType { get; set; } + public List AudiencesToAdd { get; internal set; } + + internal Result Result { get; set; } } From 395c7818ad80e9d1c538af547b4bc18f170fb6c2 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Thu, 22 Aug 2024 21:23:01 +0100 Subject: [PATCH 11/32] Removed ITokenValidationError interface. Updated tests --- .../JsonWebTokenHandler.DecryptToken.cs | 2 +- .../JsonWebTokenHandler.ReadToken.cs | 2 +- .../JsonWebTokenHandler.ValidateSignature.cs | 26 +-- ...nWebTokenHandler.ValidateToken.Internal.cs | 22 +-- .../JwtTokenUtilities.DecryptTokenResult.cs | 4 +- .../Delegates.cs | 2 +- .../Results/TokenValidationError.cs | 21 +-- .../Results/TokenValidationResult.cs | 6 +- .../Validation/Results/ValidationResult.cs | 4 +- .../Validation/ValidationParameters.cs | 2 +- .../Validation/Validators.Algorithm.cs | 4 +- .../Validation/Validators.Audience.cs | 4 +- .../Validation/Validators.Issuer.cs | 6 +- .../Validation/Validators.IssuerSigningKey.cs | 6 +- .../Validation/Validators.Lifetime.cs | 4 +- .../Validation/Validators.TokenReplay.cs | 4 +- .../Validation/Validators.TokenType.cs | 4 +- .../IdentityComparer.cs | 82 ++++++++- .../AlgorithmValidationResultTests.cs | 2 +- .../AudienceValidationResultTests.cs | 8 +- .../Validation/IssuerValidationResultTests.cs | 110 +++++------- .../LifetimeValidationResultTests.cs | 165 ++++++++---------- .../Validation/ReplayValidationResultTests.cs | 131 +++++++------- .../SigningKeyValidationResultTests.cs | 118 ++++++------- 24 files changed, 376 insertions(+), 363 deletions(-) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs index f093f96c4e..5e14e25a75 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs @@ -23,7 +23,7 @@ public partial class JsonWebTokenHandler : TokenHandler /// The to be used for validating the token. /// /// The decoded / cleartext contents of the JWE. - internal Result DecryptToken( + internal Result DecryptToken( JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration configuration, diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs index 0fc5e04a7e..886b916ee6 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs @@ -20,7 +20,7 @@ public partial class JsonWebTokenHandler : TokenHandler /// returned if is null or empty. /// returned if the validationParameters.TokenReader delegate is not able to parse/read the token as a valid . /// returned if is not a valid JWT, . - internal static Result ReadToken( + internal static Result ReadToken( string token, #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging CallContext? callContext) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs index 1d99f43b3f..7e2882da69 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs @@ -27,7 +27,7 @@ public partial class JsonWebTokenHandler : TokenHandler /// Returned by the default implementation if the token is not signed, or if the validation fails. /// Returned if the algorithm is not supported by the key. /// Returned if the key cannot be resolved. - internal static Result ValidateSignature( + internal static Result ValidateSignature( JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration? configuration, @@ -91,7 +91,7 @@ internal static Result ValidateSignature( null); } - private static Result ValidateSignatureUsingAllKeys( + private static Result ValidateSignatureUsingAllKeys( JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration? configuration, @@ -101,22 +101,22 @@ private static Result ValidateSignatureUsing // 1. User specified delegate: IssuerSigningKeyResolver returned null // 2. ResolveIssuerSigningKey returned null // Try all the keys. This is the degenerate case, not concerned about perf. - (Result? configResult, bool configKidMatched, KeyMatchFailedResult? configFailedResult) = ValidateUsingKeys( + (Result? configResult, bool configKidMatched, KeyMatchFailedResult? configFailedResult) = ValidateUsingKeys( jwtToken, validationParameters, configuration?.SigningKeys, callContext); - if (configResult is Result unwrappedConfigResult) + if (configResult is Result unwrappedConfigResult) return unwrappedConfigResult; - (Result? vpResult, bool vpKidMatched, KeyMatchFailedResult? vpFailedResult) = ValidateUsingKeys( + (Result? vpResult, bool vpKidMatched, KeyMatchFailedResult? vpFailedResult) = ValidateUsingKeys( jwtToken, validationParameters, validationParameters.IssuerSigningKeys, callContext); - if (vpResult is Result unwrappedVpResult) + if (vpResult is Result unwrappedVpResult) return unwrappedVpResult; if (vpFailedResult is null && configFailedResult is null) // No keys were attempted @@ -145,7 +145,7 @@ private static Result ValidateSignatureUsing kidMatched); } - private static (Result? validResult, bool KidMatched, KeyMatchFailedResult? failedResult) ValidateUsingKeys( + private static (Result? validResult, bool KidMatched, KeyMatchFailedResult? failedResult) ValidateUsingKeys( JsonWebToken jwtToken, ValidationParameters validationParameters, ICollection? keys, @@ -160,12 +160,12 @@ private static (Result? validResult, bool Ki bool kidExists = !string.IsNullOrEmpty(jwtToken.Kid); bool kidMatched = false; IList? keysAttempted = null; - IList? errors = null; + IList? errors = null; for (int i = 0; i < keysList.Count; i++) { SecurityKey key = keysList[i]; - Result result = ValidateSignatureWithKey(jwtToken, key, validationParameters, callContext); + Result result = ValidateSignatureWithKey(jwtToken, key, validationParameters, callContext); if (result.IsSuccess) { jwtToken.SigningKey = key; @@ -189,7 +189,7 @@ private static (Result? validResult, bool Ki return (null, kidMatched, null); } - private static Result ValidateSignatureWithKey( + private static Result ValidateSignatureWithKey( JsonWebToken jsonWebToken, SecurityKey key, ValidationParameters validationParameters, @@ -207,7 +207,7 @@ private static Result ValidateSignatureWithK null); } - Result result = validationParameters.AlgorithmValidator( + Result result = validationParameters.AlgorithmValidator( jsonWebToken.Alg, key, jsonWebToken, @@ -345,10 +345,10 @@ private static void PopulateFailedResults( } private struct KeyMatchFailedResult( - IList failedResults, + IList failedResults, IList keysAttempted) { - public IList FailedResults = failedResults; + public IList FailedResults = failedResults; public IList KeysAttempted = keysAttempted; } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs index 4be8e61e9d..e3f56bbce3 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs @@ -64,7 +64,7 @@ internal async Task ValidateTokenAsync( new MessageDetail(TokenLogMessages.IDX10209, LogHelper.MarkAsNonPII(token.Length), LogHelper.MarkAsNonPII(MaximumTokenSizeInBytes)), null)); - Result result = ReadToken(token, callContext); + Result result = ReadToken(token, callContext); if (result.IsSuccess) return await ValidateTokenAsync( result.UnwrapResult(), @@ -217,13 +217,13 @@ private async ValueTask ValidateJWEAsync( CallContext callContext, CancellationToken? cancellationToken) { - Result decryptionResult = DecryptToken( + Result decryptionResult = DecryptToken( jwtToken, validationParameters, configuration, callContext); if (!decryptionResult.IsSuccess) return new ValidationResult(jwtToken, this, validationParameters, decryptionResult.UnwrapError()); - Result readResult = ReadToken(decryptionResult.UnwrapResult(), callContext); + Result readResult = ReadToken(decryptionResult.UnwrapResult(), callContext); if (!readResult.IsSuccess) return new ValidationResult(jwtToken, this, validationParameters, readResult.UnwrapError()); @@ -253,7 +253,7 @@ private async ValueTask ValidateJWSAsync( DateTime? expires = jsonWebToken.HasPayloadClaim(JwtRegisteredClaimNames.Exp) ? jsonWebToken.ValidTo : null; DateTime? notBefore = jsonWebToken.HasPayloadClaim(JwtRegisteredClaimNames.Nbf) ? jsonWebToken.ValidFrom : null; - Result lifetimeValidationResult = validationParameters.LifetimeValidator( + Result lifetimeValidationResult = validationParameters.LifetimeValidator( notBefore, expires, jsonWebToken, validationParameters, callContext); if (!lifetimeValidationResult.IsSuccess) @@ -262,7 +262,7 @@ private async ValueTask ValidateJWSAsync( if (jsonWebToken.Audiences is not IList tokenAudiences) tokenAudiences = jsonWebToken.Audiences.ToList(); - Result audienceValidationResult = validationParameters.AudienceValidator( + Result audienceValidationResult = validationParameters.AudienceValidator( tokenAudiences, jsonWebToken, validationParameters, callContext); if (!audienceValidationResult.IsSuccess) @@ -271,7 +271,7 @@ private async ValueTask ValidateJWSAsync( ValidatedLifetime = lifetimeValidationResult.UnwrapResult() }; - Result issuerValidationResult = await validationParameters.IssuerValidatorAsync( + Result issuerValidationResult = await validationParameters.IssuerValidatorAsync( jsonWebToken.Issuer, jsonWebToken, validationParameters, callContext, cancellationToken) .ConfigureAwait(false); @@ -282,7 +282,7 @@ private async ValueTask ValidateJWSAsync( ValidatedAudience = audienceValidationResult.UnwrapResult() }; - Result replayValidationResult = validationParameters.TokenReplayValidator( + Result replayValidationResult = validationParameters.TokenReplayValidator( expires, jsonWebToken.EncodedToken, validationParameters, callContext); if (!replayValidationResult.IsSuccess) @@ -297,7 +297,7 @@ private async ValueTask ValidateJWSAsync( // actor validation if (validationParameters.ValidateActor && !string.IsNullOrWhiteSpace(jsonWebToken.Actor)) { - Result actorReadingResult = ReadToken(jsonWebToken.Actor, callContext); + Result actorReadingResult = ReadToken(jsonWebToken.Actor, callContext); if (!actorReadingResult.IsSuccess) return new ValidationResult(jsonWebToken, this, validationParameters, actorReadingResult.UnwrapError()) { @@ -326,7 +326,7 @@ await ValidateJWSAsync(actorToken, actorParameters, configuration, callContext, }; } - Result typeValidationResult = validationParameters.TypeValidator( + Result typeValidationResult = validationParameters.TypeValidator( jsonWebToken.Typ, jsonWebToken, validationParameters, callContext); if (!typeValidationResult.IsSuccess) @@ -340,7 +340,7 @@ await ValidateJWSAsync(actorToken, actorParameters, configuration, callContext, }; // The signature validation delegate is yet to be migrated to ValidationParameters. - Result signatureValidationResult = ValidateSignature( + Result signatureValidationResult = ValidateSignature( jsonWebToken, validationParameters, configuration, callContext); if (!signatureValidationResult.IsSuccess) @@ -354,7 +354,7 @@ await ValidateJWSAsync(actorToken, actorParameters, configuration, callContext, ValidatedTokenType = typeValidationResult.UnwrapResult() }; - Result issuerSigningKeyValidationResult = validationParameters.IssuerSigningKeyValidator( + Result issuerSigningKeyValidationResult = validationParameters.IssuerSigningKeyValidator( signatureValidationResult.UnwrapResult(), jsonWebToken, validationParameters, configuration, callContext); if (!issuerSigningKeyValidationResult.IsSuccess) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs index 24a6182d46..b074023a7b 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs @@ -20,7 +20,7 @@ public partial class JwtTokenUtilities /// The decryption parameters container. /// The call context used for logging. /// The decrypted, and if the 'zip' claim is set, decompressed string representation of the token. - internal static Result DecryptJwtToken( + internal static Result DecryptJwtToken( JsonWebToken jsonWebToken, ValidationParameters validationParameters, JwtTokenDecryptionParameters decryptionParameters, @@ -64,7 +64,7 @@ internal static Result DecryptJwtToken( continue; } - Result result = validationParameters.AlgorithmValidator(zipAlgorithm, key, jsonWebToken, validationParameters, callContext); + Result result = validationParameters.AlgorithmValidator(zipAlgorithm, key, jsonWebToken, validationParameters, callContext); if (!result.IsSuccess) { (exceptionStrings ??= new StringBuilder()).AppendLine(result.UnwrapError().MessageDetail.Message); diff --git a/src/Microsoft.IdentityModel.Tokens/Delegates.cs b/src/Microsoft.IdentityModel.Tokens/Delegates.cs index d4ab3d76d8..491c497c28 100644 --- a/src/Microsoft.IdentityModel.Tokens/Delegates.cs +++ b/src/Microsoft.IdentityModel.Tokens/Delegates.cs @@ -205,7 +205,7 @@ namespace Microsoft.IdentityModel.Tokens /// The to be used for logging. /// This method is not expected to throw. /// The validated . - internal delegate Result SignatureValidatorDelegate(SecurityToken token, ValidationParameters validationParameters, BaseConfiguration? configuration, CallContext? callContext); + internal delegate Result SignatureValidatorDelegate(SecurityToken token, ValidationParameters validationParameters, BaseConfiguration? configuration, CallContext? callContext); /// /// Transforms the security token before signature validation. diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs index eaca50bb66..4abfd765ce 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs @@ -4,19 +4,12 @@ #nullable enable using System; -//using System.Diagnostics; +using System.Diagnostics; using System.Runtime.CompilerServices; namespace Microsoft.IdentityModel.Tokens { - internal interface ITokenValidationError - { - ValidationErrorType ErrorType { get; } - MessageDetail MessageDetail { get; } - Exception? InnerException { get; } - } - - internal struct TokenValidationError : ITokenValidationError + internal class TokenValidationError { public ValidationErrorType ErrorType { get; } public MessageDetail MessageDetail { get; } @@ -24,14 +17,15 @@ internal struct TokenValidationError : ITokenValidationError public string CallerFilePath { get; } public int CallerLineNumber { get; } - //private StackFrame? _stackFrame; + private StackFrame? _stackFrame; public TokenValidationError( ValidationErrorType errorType, MessageDetail messageDetail, Exception? innerException, [CallerFilePath] string callerFilePath = "", - [CallerLineNumber] int callerLineNumber = 0) + [CallerLineNumber] int callerLineNumber = 0 + ) { ErrorType = errorType; MessageDetail = messageDetail; @@ -39,7 +33,10 @@ public TokenValidationError( CallerFilePath = callerFilePath; CallerLineNumber = callerLineNumber; - //_stackFrame = new StackFrame(); + if (AppContextSwitches.DontFailOnMissingTid) + CallerLineNumber = 123; + + _stackFrame = new StackFrame(); } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationResult.cs index ebd1190a29..44538236af 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationResult.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationResult.cs @@ -37,7 +37,7 @@ public class TokenValidationResult // TODO - lazy creation of _validationResults private List _validationResults; - private ITokenValidationError _tokenValidationError; + private TokenValidationError _tokenValidationError; private Exception _exception; private bool _isValid; @@ -87,7 +87,7 @@ internal TokenValidationResult( ValidationParameters validationParameters, string issuer, List validationResults, - ITokenValidationError tokenValidationError) + TokenValidationError tokenValidationError) { _validationParameters = validationParameters; _tokenHandler = tokenHandler; @@ -107,7 +107,7 @@ internal TokenValidationResult( internal TokenValidationResult( TokenHandler tokenHandler, ValidationParameters validationParameters, - ITokenValidationError tokenValidationError) + TokenValidationError tokenValidationError) { _tokenHandler = tokenHandler; _tokenValidationError = tokenValidationError; diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs index 83fff576e0..ceb6ed2cc9 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs @@ -33,7 +33,7 @@ public ValidationResult( SecurityToken? securityToken, TokenHandler tokenHandler, ValidationParameters? validationParameters, - ITokenValidationError tokenValidationError) + TokenValidationError tokenValidationError) { TokenHandler = tokenHandler ?? throw new ArgumentNullException("TokenHandler cannot be null."); SecurityToken = securityToken; @@ -47,7 +47,7 @@ public ValidationResult( /// public bool IsValid { get; private set; } - public ITokenValidationError? TokenValidationError { get; private set; } + public TokenValidationError? TokenValidationError { get; private set; } /// /// Logs the validation result. diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs b/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs index c269e9fcff..e993f914f7 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs @@ -495,7 +495,7 @@ public TokenReplayValidatorDelegate TokenReplayValidator /// /// Allows overriding the delegate that will be used to validate the type of the token. - /// If the token type cannot be validated, a MUST be returned by the delegate. + /// If the token type cannot be validated, a MUST be returned by the delegate. /// Note: the 'type' parameter may be null if it couldn't be extracted from its usual location. /// Implementations that need to resolve it from a different location can use the 'token' parameter. /// diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs index e85a6e84c0..69673f2fb9 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs @@ -19,7 +19,7 @@ namespace Microsoft.IdentityModel.Tokens /// /// A that contains the results of validating the algorithm. /// This delegate is not expected to throw. - internal delegate Result AlgorithmValidatorDelegate( + internal delegate Result AlgorithmValidatorDelegate( string algorithm, SecurityKey securityKey, SecurityToken securityToken, @@ -37,7 +37,7 @@ public static partial class Validators /// required for validation. /// #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging - internal static Result ValidateAlgorithm( + internal static Result ValidateAlgorithm( string algorithm, SecurityKey securityKey, SecurityToken securityToken, diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs index 0492afa981..74ee278ded 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs @@ -18,7 +18,7 @@ namespace Microsoft.IdentityModel.Tokens /// /// A that contains the results of validating the issuer. /// This delegate is not expected to throw. - internal delegate Result AudienceValidatorDelegate( + internal delegate Result AudienceValidatorDelegate( IList audiences, SecurityToken? securityToken, ValidationParameters validationParameters, @@ -42,7 +42,7 @@ public static partial class Validators /// If none of the 'audiences' matched either or one of . /// An EXACT match is required. #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging - internal static Result ValidateAudience(IList tokenAudiences, SecurityToken? securityToken, ValidationParameters validationParameters, CallContext callContext) + internal static Result ValidateAudience(IList tokenAudiences, SecurityToken? securityToken, ValidationParameters validationParameters, CallContext callContext) #pragma warning restore CA1801 { if (validationParameters == null) diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs index e3a0892aef..e3e5957d01 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs @@ -30,7 +30,7 @@ internal record struct ValidatedIssuer(string Issuer, IssuerValidationSource Val /// /// An that contains the results of validating the issuer. /// This delegate is not expected to throw. - internal delegate Task> IssuerValidationDelegateAsync( + internal delegate Task> IssuerValidationDelegateAsync( string issuer, SecurityToken securityToken, ValidationParameters validationParameters, @@ -52,7 +52,7 @@ public static partial class Validators /// /// An that contains either the issuer that was validated or an error. /// An EXACT match is required. - internal static async Task> ValidateIssuerAsync( + internal static async Task> ValidateIssuerAsync( string issuer, SecurityToken securityToken, ValidationParameters validationParameters, @@ -62,10 +62,12 @@ internal static async Task> Valid CancellationToken? cancellationToken) { if (string.IsNullOrWhiteSpace(issuer)) + { return new TokenValidationError( ValidationErrorType.SecurityTokenInvalidIssuer, new MessageDetail(LogMessages.IDX10211), null); + } if (validationParameters == null) return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs index 6033d385c6..abd9359f75 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs @@ -23,7 +23,7 @@ internal record struct ValidatedSigningKeyLifetime(DateTime? ValidFrom, DateTime /// The to be used for logging. /// A that contains the results of validating the issuer. /// This delegate is not expected to throw. - internal delegate Result IssuerSigningKeyValidatorDelegate( + internal delegate Result IssuerSigningKeyValidatorDelegate( SecurityKey signingKey, SecurityToken securityToken, ValidationParameters validationParameters, @@ -47,7 +47,7 @@ public static partial class Validators /// if 'securityKey' is null and ValidateIssuerSigningKey is true. /// if 'securityToken' is null and ValidateIssuerSigningKey is true. /// if 'validationParameters' is null. - internal static Result ValidateIssuerSigningKey( + internal static Result ValidateIssuerSigningKey( SecurityKey securityKey, SecurityToken securityToken, ValidationParameters validationParameters, @@ -80,7 +80,7 @@ internal static Result Valid /// The to be used for validating the token. /// #pragma warning disable CA1801 // Review unused parameters - internal static Result ValidateIssuerSigningKeyLifeTime( + internal static Result ValidateIssuerSigningKeyLifeTime( SecurityKey securityKey, ValidationParameters validationParameters, CallContext? callContext) diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs index 559bc11d3e..ade4486592 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs @@ -20,7 +20,7 @@ internal record struct ValidatedLifetime(DateTime? NotBefore, DateTime? Expires) /// /// A that contains the results of validating the issuer. /// This delegate is not expected to throw. - internal delegate Result LifetimeValidatorDelegate( + internal delegate Result LifetimeValidatorDelegate( DateTime? notBefore, DateTime? expires, SecurityToken? securityToken, @@ -48,7 +48,7 @@ public static partial class Validators /// If 'expires' is < DateTime.UtcNow. /// All time comparisons apply . #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging - internal static Result ValidateLifetime( + internal static Result ValidateLifetime( DateTime? notBefore, DateTime? expires, SecurityToken? securityToken, diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs index b5f390a19c..b279c10454 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs @@ -16,7 +16,7 @@ namespace Microsoft.IdentityModel.Tokens /// /// A that contains the results of validating the token. /// This delegate is not expected to throw. - internal delegate Result TokenReplayValidatorDelegate( + internal delegate Result TokenReplayValidatorDelegate( DateTime? expirationTime, string securityToken, ValidationParameters validationParameters, @@ -40,7 +40,7 @@ public static partial class Validators /// If the 'securityToken' is found in the cache. /// If the 'securityToken' could not be added to the . #pragma warning disable CA1801 // Review unused parameters - internal static Result ValidateTokenReplay(DateTime? expirationTime, string securityToken, ValidationParameters validationParameters, CallContext callContext) + internal static Result ValidateTokenReplay(DateTime? expirationTime, string securityToken, ValidationParameters validationParameters, CallContext callContext) #pragma warning restore CA1801 // Review unused parameters { if (string.IsNullOrWhiteSpace(securityToken)) diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs index 35a4c667d4..4b54c085dd 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs @@ -21,7 +21,7 @@ internal record struct ValidatedTokenType(string Type, int ValidTypeCount); /// /// A that contains the results of validating the token type. /// An EXACT match is required. (case sensitive) is used for comparing against . - internal delegate Result TypeValidatorDelegate( + internal delegate Result TypeValidatorDelegate( string? type, SecurityToken? securityToken, ValidationParameters validationParameters, @@ -39,7 +39,7 @@ public static partial class Validators /// A that contains the results of validating the token type. /// An EXACT match is required. (case sensitive) is used for comparing against . #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging - internal static Result ValidateTokenType( + internal static Result ValidateTokenType( string? type, SecurityToken? securityToken, ValidationParameters validationParameters, diff --git a/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs b/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs index 4c96a3150a..306106b47e 100644 --- a/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs +++ b/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs @@ -504,6 +504,21 @@ public static bool AreDateTimesEqual(object object1, object object2, CompareCont return context.Merge(localContext); } + public static bool AreDateTimesEqualWithEpsilon(object object1, object object2, int epsilon, CompareContext context) + { + var localContext = new CompareContext(context); + if (!ContinueCheckingEquality(object1, object2, localContext)) + return context.Merge(localContext); + + DateTime dateTime1 = (DateTime)object1; + DateTime dateTime2 = (DateTime)object2; + + if (!AreDatesEqualWithEpsilon(dateTime1, dateTime2, epsilon)) + localContext.Diffs.Add($"dateTime1 != dateTime2. '{dateTime1}' != '{dateTime2}'."); + + return context.Merge(localContext); + } + public static bool AreEqual(object object1, object object2) { return AreEqual(object1, object2, CompareContext.Default); @@ -1213,7 +1228,72 @@ public static bool AreTimeSpansEqual(object object1, object object2, CompareCont return context.Merge(localContext); } - internal static bool AreTokenValidationErrorsEqual(ITokenValidationError tokenValidationError1, ITokenValidationError tokenValidationError2, CompareContext context) + internal static bool AreValidatedIssuersEqual(ValidatedIssuer validatedIssuer1, ValidatedIssuer validatedIssuer2, CompareContext context) + { + var localContext = new CompareContext(context); + + AreStringsEqual( + validatedIssuer1.Issuer, + validatedIssuer2.Issuer, + "validatedIssuer1.Issuer", + "validatedIssuer2.Issuer", + localContext); + + AreIntsEqual( + (int)validatedIssuer1.ValidationSource, + (int)validatedIssuer2.ValidationSource, + "validatedIssuer1.ValidationSource", + "validatedIssuer2.ValidationSource", + localContext); + + return context.Merge(localContext); + } + + internal static bool AreValidatedLifetimesEqual(ValidatedLifetime validatedLifetime1, ValidatedLifetime validatedLifetime2, CompareContext context) + { + var localContext = new CompareContext(context); + + AreDateTimesEqualWithEpsilon( + validatedLifetime1.NotBefore, + validatedLifetime2.NotBefore, + 1, + localContext); + + AreDateTimesEqualWithEpsilon( + validatedLifetime1.Expires, + validatedLifetime2.Expires, + 1, + localContext); + + return context.Merge(localContext); + } + + internal static bool AreValidatedSigningKeyLifetimesEqual(ValidatedSigningKeyLifetime validatedSigningKeyLifetime1, ValidatedSigningKeyLifetime validatedSigningKeyLifetime2, CompareContext context) + { + var localContext = new CompareContext(context); + + AreDateTimesEqualWithEpsilon( + validatedSigningKeyLifetime1.ValidFrom, + validatedSigningKeyLifetime2.ValidFrom, + 1, + localContext); + + AreDateTimesEqualWithEpsilon( + validatedSigningKeyLifetime1.ValidTo, + validatedSigningKeyLifetime2.ValidTo, + 1, + localContext); + + AreDateTimesEqualWithEpsilon( + validatedSigningKeyLifetime1.ValidationTime, + validatedSigningKeyLifetime2.ValidationTime, + 1, + localContext); + + return context.Merge(localContext); + } + + internal static bool AreTokenValidationErrorsEqual(TokenValidationError tokenValidationError1, TokenValidationError tokenValidationError2, CompareContext context) { var localContext = new CompareContext(context); diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs index 9ffc5a59df..3e4a2efa1c 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs @@ -15,7 +15,7 @@ public void ValidateAlgorithm(AlgorithmTheoryData theoryData) { CompareContext context = TestUtilities.WriteHeader($"{this}.AlgorithmValidationResultTests", theoryData); - Result result = Validators.ValidateAlgorithm( + Result result = Validators.ValidateAlgorithm( theoryData.Algorithm, theoryData.SecurityKey, theoryData.SecurityToken, diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs index 0d1676b94c..523ba85d99 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs @@ -25,7 +25,7 @@ public void ValidateAudienceParameters(AudienceValidationTheoryData theoryData) theoryData.ValidationParameters.ValidAudiences.Add(audience); } - Result result = Validators.ValidateAudience( + Result result = Validators.ValidateAudience( theoryData.Audiences, theoryData.SecurityToken, theoryData.ValidationParameters, @@ -47,9 +47,9 @@ public void ValidateAudienceParameters(AudienceValidationTheoryData theoryData) theoryData.ExpectedException.ProcessException(result.UnwrapError().InnerException); else theoryData.ExpectedException.ProcessNoException(); - - TestUtilities.AssertFailIfErrors(context); } + + TestUtilities.AssertFailIfErrors(context); } public static TheoryData ValidateAudienceTestCases @@ -377,7 +377,7 @@ public class AudienceValidationTheoryData : TheoryDataBase public List AudiencesToAdd { get; internal set; } - internal Result Result { get; set; } + internal Result Result { get; set; } } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs index ad31043587..cd3970da62 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs @@ -2,9 +2,9 @@ // Licensed under the MIT License. using System; -using System.Diagnostics; using System.Threading; using System.Threading.Tasks; +using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.TestUtils; @@ -24,22 +24,32 @@ public async Task IssuerValidatorAsyncTests(IssuerValidationResultsTheoryData th if (theoryData.ValidIssuerToAdd != null) theoryData.ValidationParameters.ValidIssuers.Add(theoryData.ValidIssuerToAdd); - IssuerValidationResult issuerValidationResult = await Validators.ValidateIssuerAsync( + Result result = await Validators.ValidateIssuerAsync( theoryData.Issuer, theoryData.SecurityToken, theoryData.ValidationParameters, new CallContext(), CancellationToken.None).ConfigureAwait(false); - if (issuerValidationResult.Exception != null) - theoryData.ExpectedException.ProcessException(issuerValidationResult.Exception, context); + if (result.IsSuccess) + { + IdentityComparer.AreValidatedIssuersEqual( + theoryData.Result.UnwrapResult(), + result.UnwrapResult(), + context); + } else - theoryData.ExpectedException.ProcessNoException(); - - IdentityComparer.AreIssuerValidationResultsEqual( - issuerValidationResult, - theoryData.IssuerValidationResult, - context); + { + IdentityComparer.AreTokenValidationErrorsEqual( + result.UnwrapError(), + theoryData.Result.UnwrapError(), + context); + + if (result.UnwrapError().InnerException is not null) + theoryData.ExpectedException.ProcessException(result.UnwrapError().InnerException); + else + theoryData.ExpectedException.ProcessNoException(); + } TestUtilities.AssertFailIfErrors(context); } @@ -57,67 +67,49 @@ public static TheoryData IssuerValdationResul theoryData.Add(new IssuerValidationResultsTheoryData("NULL_Issuer") { - ExpectedException = ExpectedException.SecurityTokenInvalidIssuerException("IDX10211:"), - IssuerValidationResult = new IssuerValidationResult( - null, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10211, - LogHelper.MarkAsNonPII(null), - LogHelper.MarkAsNonPII(validIssuer), - LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(null)), - LogHelper.MarkAsNonPII(null)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidIssuer)), - IsValid = false, + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidIssuer, + new MessageDetail( + LogMessages.IDX10211, + LogHelper.MarkAsNonPII(null), + LogHelper.MarkAsNonPII(validIssuer), + LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(null)), + LogHelper.MarkAsNonPII(null)), + null), SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, issClaim), ValidationParameters = new ValidationParameters() }); theoryData.Add(new IssuerValidationResultsTheoryData("NULL_ValidationParameters") { - ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), Issuer = issClaim, - IssuerValidationResult = new IssuerValidationResult( - issClaim, - ValidationFailureType.NullArgument, - new ExceptionDetail( + Result = new TokenValidationError( + ValidationErrorType.ArgumentNull, new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), - ExceptionDetail.ExceptionType.ArgumentNull, - null)), - IsValid = false, + null), SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, issClaim), ValidationParameters = null }); theoryData.Add(new IssuerValidationResultsTheoryData("NULL_SecurityToken") { - ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), Issuer = issClaim, - IssuerValidationResult = new IssuerValidationResult( - issClaim, - ValidationFailureType.NullArgument, - new ExceptionDetail( + Result = new TokenValidationError( + ValidationErrorType.ArgumentNull, new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), - ExceptionDetail.ExceptionType.ArgumentNull, - null)), - IsValid = false, + null), SecurityToken = null, ValidationParameters = new ValidationParameters() }); theoryData.Add(new IssuerValidationResultsTheoryData("Valid_FromConfig") { - ExpectedException = ExpectedException.NoExceptionExpected, Issuer = issClaim, - IssuerValidationResult = new IssuerValidationResult( - issClaim, - IssuerValidationResult.ValidationSource.IssuerIsConfigurationIssuer), - IsValid = true, + Result = new ValidatedIssuer(issClaim, IssuerValidationSource.IssuerIsConfigurationIssuer), SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, issClaim), ValidationParameters = new ValidationParameters() { @@ -127,12 +119,8 @@ public static TheoryData IssuerValdationResul theoryData.Add(new IssuerValidationResultsTheoryData("Valid_FromValidationParametersValidIssuers") { - ExpectedException = ExpectedException.NoExceptionExpected, Issuer = issClaim, - IssuerValidationResult = new IssuerValidationResult( - issClaim, - IssuerValidationResult.ValidationSource.IssuerIsAmongValidIssuers), - IsValid = true, + Result = new ValidatedIssuer(issClaim, IssuerValidationSource.IssuerIsAmongValidIssuers), SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, issClaim), ValidationParameters = new ValidationParameters(), ValidIssuerToAdd = issClaim @@ -140,19 +128,15 @@ public static TheoryData IssuerValdationResul theoryData.Add(new IssuerValidationResultsTheoryData("Invalid_Issuer") { - ExpectedException = ExpectedException.SecurityTokenInvalidIssuerException("IDX10212:"), Issuer = issClaim, - IssuerValidationResult = new IssuerValidationResult( - issClaim, - ValidationFailureType.IssuerValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10212, - LogHelper.MarkAsNonPII(issClaim), - LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validIssuers)), - LogHelper.MarkAsNonPII(null)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidIssuer)), - IsValid = false, + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidIssuer, + new MessageDetail( + LogMessages.IDX10212, + LogHelper.MarkAsNonPII(issClaim), + LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validIssuers)), + LogHelper.MarkAsNonPII(null)), + null), SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, issClaim), ValidationParameters = new ValidationParameters(), ValidIssuerToAdd = validIssuer @@ -173,9 +157,7 @@ public IssuerValidationResultsTheoryData(string testId) : base(testId) public string Issuer { get; set; } - internal IssuerValidationResult IssuerValidationResult { get; set; } - - public bool IsValid { get; set; } + internal Result Result { get; set; } public SecurityToken SecurityToken { get; set; } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs index f8b6a4efc3..1b73e54e07 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs @@ -2,7 +2,7 @@ // Licensed under the MIT License. using System; -using System.Diagnostics; +using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.TestUtils; using Xunit; @@ -16,22 +16,34 @@ public void ValidateLifetime(ValidateLifetimeTheoryData theoryData) { CompareContext context = TestUtilities.WriteHeader($"{this}.LifetimeValidatorTests", theoryData); - LifetimeValidationResult lifetimeValidationResult = Validators.ValidateLifetime( + Result result = Validators.ValidateLifetime( theoryData.NotBefore, theoryData.Expires, theoryData.SecurityToken, theoryData.ValidationParameters, new CallContext()); - if (lifetimeValidationResult.Exception == null) - theoryData.ExpectedException.ProcessNoException(); + if (result.IsSuccess) + { + IdentityComparer.AreValidatedLifetimesEqual( + theoryData.Result.UnwrapResult(), + result.UnwrapResult(), + context); + } else - theoryData.ExpectedException.ProcessException(lifetimeValidationResult.Exception, context); + { + IdentityComparer.AreTokenValidationErrorsEqual( + result.UnwrapError(), + theoryData.Result.UnwrapError(), + context); - IdentityComparer.AreLifetimeValidationResultsEqual( - lifetimeValidationResult, - theoryData.LifetimeValidationResult, - context); + if (result.UnwrapError().InnerException is not null) + theoryData.ExpectedException.ProcessException(result.UnwrapError().InnerException); + else + theoryData.ExpectedException.ProcessNoException(); + + TestUtilities.AssertFailIfErrors(context); + } TestUtilities.AssertFailIfErrors(context); } @@ -57,14 +69,14 @@ public static TheoryData ValidateLifetimeTestCases { Expires = oneHourFromNow, NotBefore = oneHourAgo, - LifetimeValidationResult = new LifetimeValidationResult(oneHourAgo, oneHourFromNow), + Result = new ValidatedLifetime(oneHourAgo, oneHourFromNow), ValidationParameters = new ValidationParameters() }, new ValidateLifetimeTheoryData("Valid_NotBeforeIsNull") { Expires = oneHourFromNow, NotBefore = null, - LifetimeValidationResult = new LifetimeValidationResult(null, oneHourFromNow), + Result = new ValidatedLifetime(null, oneHourFromNow), ValidationParameters = new ValidationParameters() }, new ValidateLifetimeTheoryData("Valid_SkewForward") @@ -72,137 +84,98 @@ public static TheoryData ValidateLifetimeTestCases Expires = oneHourFromNow, NotBefore = twoMinutesFromNow, ValidationParameters = new ValidationParameters { ClockSkew = TimeSpan.FromMinutes(5) }, - LifetimeValidationResult = new LifetimeValidationResult(twoMinutesFromNow, oneHourFromNow), + Result = new ValidatedLifetime(twoMinutesFromNow, oneHourFromNow), }, new ValidateLifetimeTheoryData("Valid_SkewBackward") { Expires = oneMinuteAgo, NotBefore = twoMinutesAgo, ValidationParameters = new ValidationParameters { ClockSkew = TimeSpan.FromMinutes(5) }, - LifetimeValidationResult = new LifetimeValidationResult(twoMinutesAgo, oneMinuteAgo), + Result = new ValidatedLifetime(twoMinutesAgo, oneMinuteAgo), }, new ValidateLifetimeTheoryData("Invalid_ValidationParametersIsNull") { Expires = oneHourFromNow, NotBefore = oneHourAgo, ValidationParameters = null, - ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), - LifetimeValidationResult = new LifetimeValidationResult( - oneHourAgo, - oneHourFromNow, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - "validationParameters"), - ExceptionDetail.ExceptionType.ArgumentNull, - null)), + Result = new TokenValidationError( + ValidationErrorType.ArgumentNull, + new MessageDetail(LogMessages.IDX10000, "validationParameters"), + null), }, new ValidateLifetimeTheoryData("Invalid_ExpiresIsNull") { NotBefore = oneHourAgo, ValidationParameters = new ValidationParameters(), - ExpectedException = ExpectedException.SecurityTokenNoExpirationException("IDX10225:"), - LifetimeValidationResult = new LifetimeValidationResult( - oneHourAgo, - null, - ValidationFailureType.LifetimeValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10225, - "null"), - ExceptionDetail.ExceptionType.SecurityTokenNoExpiration, - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenNoExpiration, + new MessageDetail(LogMessages.IDX10225, "null"), + null), }, new ValidateLifetimeTheoryData("Invalid_NotBeforeIsAfterExpires") { Expires = oneHourAgo, NotBefore = oneHourFromNow, ValidationParameters = new ValidationParameters(), - ExpectedException = ExpectedException.SecurityTokenInvalidLifetimeException("IDX10224:"), - LifetimeValidationResult = new LifetimeValidationResult( - oneHourFromNow, // notBefore - oneHourAgo, // expires - ValidationFailureType.LifetimeValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10224, - LogHelper.MarkAsNonPII(oneHourFromNow), - LogHelper.MarkAsNonPII(oneHourAgo)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidLifetime, - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidLifetime, + new MessageDetail( + LogMessages.IDX10224, + LogHelper.MarkAsNonPII(oneHourFromNow), + LogHelper.MarkAsNonPII(oneHourAgo)), + null), }, new ValidateLifetimeTheoryData("Invalid_NotYetValid") { Expires = twoHoursFromNow, NotBefore = oneHourFromNow, ValidationParameters = new ValidationParameters(), - ExpectedException = ExpectedException.SecurityTokenNotYetValidException("IDX10222:"), - LifetimeValidationResult = new LifetimeValidationResult( - oneHourFromNow, - twoHoursFromNow, - ValidationFailureType.LifetimeValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10222, - LogHelper.MarkAsNonPII(oneHourFromNow), - LogHelper.MarkAsNonPII(now)), - ExceptionDetail.ExceptionType.SecurityTokenNotYetValid, - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenNotYetValid, + new MessageDetail( + LogMessages.IDX10222, + LogHelper.MarkAsNonPII(oneHourFromNow), + LogHelper.MarkAsNonPII(now)), + null), }, new ValidateLifetimeTheoryData("Invalid_Expired") { Expires = oneHourAgo, NotBefore = twoHoursAgo, ValidationParameters = new ValidationParameters(), - ExpectedException = ExpectedException.SecurityTokenExpiredException("IDX10223:"), - LifetimeValidationResult = new LifetimeValidationResult( - twoHoursAgo, - oneHourAgo, - ValidationFailureType.LifetimeValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10223, - LogHelper.MarkAsNonPII(oneHourAgo), - LogHelper.MarkAsNonPII(now)), - ExceptionDetail.ExceptionType.SecurityTokenExpired, - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenExpired, + new MessageDetail( + LogMessages.IDX10223, + LogHelper.MarkAsNonPII(oneHourAgo), + LogHelper.MarkAsNonPII(now)), + null), }, new ValidateLifetimeTheoryData("Invalid_NotYetValid_SkewForward") { Expires = oneHourFromNow, NotBefore = sixMinutesFromNow, ValidationParameters = new ValidationParameters { ClockSkew = TimeSpan.FromMinutes(5) }, - ExpectedException = ExpectedException.SecurityTokenNotYetValidException("IDX10222:"), - LifetimeValidationResult = new LifetimeValidationResult( - sixMinutesFromNow, - oneHourFromNow, - ValidationFailureType.LifetimeValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10222, - LogHelper.MarkAsNonPII(sixMinutesFromNow), - LogHelper.MarkAsNonPII(now)), - ExceptionDetail.ExceptionType.SecurityTokenNotYetValid, - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenNotYetValid, + new MessageDetail( + LogMessages.IDX10222, + LogHelper.MarkAsNonPII(sixMinutesFromNow), + LogHelper.MarkAsNonPII(now)), + null), }, new ValidateLifetimeTheoryData("Invalid_Expired_SkewBackward") { Expires = sixMinutesAgo, NotBefore = twoHoursAgo, ValidationParameters = new ValidationParameters { ClockSkew = TimeSpan.FromMinutes(5) }, - ExpectedException = ExpectedException.SecurityTokenExpiredException("IDX10223:"), - LifetimeValidationResult = new LifetimeValidationResult( - twoHoursAgo, - sixMinutesAgo, - ValidationFailureType.LifetimeValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10223, - LogHelper.MarkAsNonPII(sixMinutesAgo), - LogHelper.MarkAsNonPII(now)), - ExceptionDetail.ExceptionType.SecurityTokenExpired, - null)), + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenExpired, + new MessageDetail( + LogMessages.IDX10223, + LogHelper.MarkAsNonPII(sixMinutesAgo), + LogHelper.MarkAsNonPII(now)), + null), } }; } @@ -223,7 +196,7 @@ public ValidateLifetimeTheoryData(string testId) : base(testId) internal ValidationParameters ValidationParameters { get; set; } - internal LifetimeValidationResult LifetimeValidationResult { get; set; } + internal Result Result { get; set; } internal ValidationFailureType ValidationFailureType { get; set; } } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs index 9ff01eed65..137fc6c329 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs @@ -2,7 +2,7 @@ // Licensed under the MIT License. using System; -using System.Diagnostics; +using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.TestUtils; using Xunit; @@ -16,24 +16,34 @@ public void ValidateTokenReplay(TokenReplayTheoryData theoryData) { CompareContext context = TestUtilities.WriteHeader($"{this}.TokenReplayValidationResultTests", theoryData); - ReplayValidationResult replayValidationResult = Validators.ValidateTokenReplay( + Result result = Validators.ValidateTokenReplay( theoryData.ExpirationTime, theoryData.SecurityToken, theoryData.ValidationParameters, new CallContext()); - if (replayValidationResult.Exception != null) - theoryData.ExpectedException.ProcessException(replayValidationResult.Exception); + if (result.IsSuccess) + { + IdentityComparer.AreDateTimesEqualWithEpsilon( + result.UnwrapResult(), + theoryData.Result.UnwrapResult(), + 1, + context); + } else - theoryData.ExpectedException.ProcessNoException(); + { + IdentityComparer.AreTokenValidationErrorsEqual( + result.UnwrapError(), + theoryData.Result.UnwrapError(), + context); - IdentityComparer.AreTokenReplayValidationResultsEqual( - replayValidationResult, - theoryData.ReplayValidationResult, - context); + if (result.UnwrapError().InnerException is not null) + theoryData.ExpectedException.ProcessException(result.UnwrapError().InnerException); + else + theoryData.ExpectedException.ProcessNoException(); + } TestUtilities.AssertFailIfErrors(context); - } public static TheoryData TokenReplayValidationTestCases @@ -55,7 +65,7 @@ public static TheoryData TokenReplayValidationTestCases { TokenReplayCache = null }, - ReplayValidationResult = new ReplayValidationResult(oneHourAgo) + Result = oneHourAgo, }, new TokenReplayTheoryData { @@ -66,7 +76,7 @@ public static TheoryData TokenReplayValidationTestCases { TokenReplayCache = new TokenReplayCache { OnAddReturnValue = true, OnFindReturnValue = false }, }, - ReplayValidationResult = new ReplayValidationResult(oneHourFromNow) + Result = oneHourFromNow, }, new TokenReplayTheoryData { @@ -74,16 +84,12 @@ public static TheoryData TokenReplayValidationTestCases ExpirationTime = now, SecurityToken = null, ValidationParameters = new ValidationParameters(), - ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), - ReplayValidationResult = new ReplayValidationResult( - now, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII("securityToken")), - ExceptionDetail.ExceptionType.ArgumentNull, - null)) + Result = new TokenValidationError( + ValidationErrorType.ArgumentNull, + new MessageDetail( + LogMessages.IDX10000, + LogHelper.MarkAsNonPII("securityToken")), + null), }, new TokenReplayTheoryData { @@ -91,16 +97,12 @@ public static TheoryData TokenReplayValidationTestCases ExpirationTime = now, SecurityToken = string.Empty, ValidationParameters = new ValidationParameters(), - ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), - ReplayValidationResult = new ReplayValidationResult( - now, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII("securityToken")), - ExceptionDetail.ExceptionType.ArgumentNull, - null)) + Result = new TokenValidationError( + ValidationErrorType.ArgumentNull, + new MessageDetail( + LogMessages.IDX10000, + LogHelper.MarkAsNonPII("securityToken")), + null), }, new TokenReplayTheoryData { @@ -108,16 +110,12 @@ public static TheoryData TokenReplayValidationTestCases ExpirationTime = now, SecurityToken = "token", ValidationParameters = null, - ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), - ReplayValidationResult = new ReplayValidationResult( - now, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII("validationParameters")), - ExceptionDetail.ExceptionType.ArgumentNull, - null)) + Result = new TokenValidationError( + ValidationErrorType.ArgumentNull, + new MessageDetail( + LogMessages.IDX10000, + LogHelper.MarkAsNonPII("validationParameters")), + null), }, new TokenReplayTheoryData { @@ -132,16 +130,12 @@ public static TheoryData TokenReplayValidationTestCases OnFindReturnValue = false } }, - ExpectedException = ExpectedException.SecurityTokenReplayDetected("IDX10227:"), - ReplayValidationResult = new ReplayValidationResult( - null, - ValidationFailureType.TokenReplayValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10227, - LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), - ExceptionDetail.ExceptionType.SecurityTokenReplayDetected, - null)) + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenReplayDetected, + new MessageDetail( + LogMessages.IDX10227, + LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), + null), }, new TokenReplayTheoryData { @@ -156,16 +150,12 @@ public static TheoryData TokenReplayValidationTestCases OnFindReturnValue = true }, }, - ExpectedException = ExpectedException.SecurityTokenReplayDetected("IDX10228:"), - ReplayValidationResult = new ReplayValidationResult( - oneHourFromNow, - ValidationFailureType.TokenReplayValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10228, - LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), - ExceptionDetail.ExceptionType.SecurityTokenReplayDetected, - null)) + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenReplayDetected, + new MessageDetail( + LogMessages.IDX10228, + LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), + null), }, new TokenReplayTheoryData { @@ -181,15 +171,12 @@ public static TheoryData TokenReplayValidationTestCases } }, ExpectedException = ExpectedException.SecurityTokenReplayAddFailed("IDX10229:"), - ReplayValidationResult = new ReplayValidationResult( - oneHourFromNow, - ValidationFailureType.TokenReplayValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10229, - LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), - ExceptionDetail.ExceptionType.SecurityTokenReplayDetected, - null)) + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenReplayDetected, + new MessageDetail( + LogMessages.IDX10229, + LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), + null), } }; } @@ -204,6 +191,6 @@ public class TokenReplayTheoryData : TheoryDataBase internal ValidationParameters ValidationParameters { get; set; } - internal ReplayValidationResult ReplayValidationResult { get; set; } + internal Result Result { get; set; } } } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs index c6c38d3474..eb4041e147 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs @@ -2,8 +2,8 @@ // Licensed under the MIT License. using System; -using System.Diagnostics; using System.IdentityModel.Tokens.Jwt; +using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.TestUtils; using Xunit; @@ -17,22 +17,32 @@ public void SecurityKey(SigningKeyValidationTheoryData theoryData) { CompareContext context = TestUtilities.WriteHeader($"{this}.SigningKeyValidationResultTests", theoryData); - SigningKeyValidationResult signingKeyValidationResult = Validators.ValidateIssuerSigningKey( + Result result = Validators.ValidateIssuerSigningKey( theoryData.SecurityKey, theoryData.SecurityToken, theoryData.ValidationParameters, theoryData.BaseConfiguration, new CallContext()); - if (signingKeyValidationResult.Exception != null) - theoryData.ExpectedException.ProcessException(signingKeyValidationResult.Exception); + if (result.IsSuccess) + { + IdentityComparer.AreValidatedSigningKeyLifetimesEqual( + theoryData.Result.UnwrapResult(), + result.UnwrapResult(), + context); + } else - theoryData.ExpectedException.ProcessNoException(); + { + IdentityComparer.AreTokenValidationErrorsEqual( + result.UnwrapError(), + theoryData.Result.UnwrapError(), + context); - IdentityComparer.AreSigningKeyValidationResultsEqual( - signingKeyValidationResult, - theoryData.SigningKeyValidationResult, - context); + if (result.UnwrapError().InnerException is not null) + theoryData.ExpectedException.ProcessException(result.UnwrapError().InnerException); + else + theoryData.ExpectedException.ProcessNoException(); + } TestUtilities.AssertFailIfErrors(context); } @@ -50,91 +60,75 @@ public static TheoryData SigningKeyValidationTes new SigningKeyValidationTheoryData { TestId = "Valid_SecurityTokenIsPresent", - ExpectedException = ExpectedException.NoExceptionExpected, SecurityKey = KeyingMaterial.SymmetricSecurityKey2_256, SecurityToken = new JwtSecurityToken(), ValidationParameters = new ValidationParameters(), - SigningKeyValidationResult = new SigningKeyValidationResult(KeyingMaterial.SymmetricSecurityKey2_256) + Result = new ValidatedSigningKeyLifetime(null, null, utcNow) }, new SigningKeyValidationTheoryData { TestId = "Invalid_SecurityKeyIsNull", - ExpectedException = ExpectedException.ArgumentNullException(substringExpected: "IDX10253:"), SecurityKey = null, SecurityToken = new JwtSecurityToken(), ValidationParameters = new ValidationParameters(), - SigningKeyValidationResult = new SigningKeyValidationResult( - null, // SecurityKey - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail(LogMessages.IDX10253), - ExceptionDetail.ExceptionType.ArgumentNull)) + Result = new TokenValidationError( + ValidationErrorType.ArgumentNull, + new MessageDetail(LogMessages.IDX10253), + null), }, new SigningKeyValidationTheoryData { TestId = "Invalid_SecurityTokenIsNull", - ExpectedException = ExpectedException.ArgumentNullException(), SecurityKey = KeyingMaterial.SymmetricSecurityKey2_256, SecurityToken = null, ValidationParameters = new ValidationParameters (), - SigningKeyValidationResult = new SigningKeyValidationResult( - KeyingMaterial.SymmetricSecurityKey2_256, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII("securityToken")), - ExceptionDetail.ExceptionType.ArgumentNull)) + Result = new TokenValidationError( + ValidationErrorType.ArgumentNull, + new MessageDetail( + LogMessages.IDX10000, + LogHelper.MarkAsNonPII("securityToken")), + null), }, new SigningKeyValidationTheoryData { TestId = "Invalid_ValidationParametersIsNull", - ExpectedException = ExpectedException.ArgumentNullException(), SecurityKey = KeyingMaterial.SymmetricSecurityKey2_256, SecurityToken = new JwtSecurityToken(), ValidationParameters = null, - SigningKeyValidationResult = new SigningKeyValidationResult( - KeyingMaterial.SymmetricSecurityKey2_256, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII("validationParameters")), - ExceptionDetail.ExceptionType.ArgumentNull)) + Result = new TokenValidationError( + ValidationErrorType.ArgumentNull, + new MessageDetail( + LogMessages.IDX10000, + LogHelper.MarkAsNonPII("validationParameters")), + null), }, new SigningKeyValidationTheoryData { TestId = "Invalid_SecurityKeyIsExpired", - ExpectedException = ExpectedException.SecurityTokenInvalidSigningKeyException(substringExpected: "IDX10249:"), SecurityKey = KeyingMaterial.ExpiredX509SecurityKey_Public, SecurityToken = new JwtSecurityToken(), ValidationParameters = new ValidationParameters (), - SigningKeyValidationResult = new SigningKeyValidationResult( - KeyingMaterial.ExpiredX509SecurityKey_Public, - ValidationFailureType.SigningKeyValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10249, - LogHelper.MarkAsNonPII(utcExpired), - LogHelper.MarkAsNonPII(utcNow)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidSigningKey)) + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidSigningKey, + new MessageDetail( + LogMessages.IDX10249, + LogHelper.MarkAsNonPII(utcExpired), + LogHelper.MarkAsNonPII(utcNow)), + null), }, new SigningKeyValidationTheoryData { TestId = "Invalid_SecurityKeyIsNotYetValid", - ExpectedException = ExpectedException.SecurityTokenInvalidSigningKeyException(substringExpected: "IDX10248:"), SecurityKey = KeyingMaterial.NotYetValidX509SecurityKey_Public, SecurityToken = new JwtSecurityToken(), ValidationParameters = new ValidationParameters (), - SigningKeyValidationResult = new SigningKeyValidationResult( - KeyingMaterial.NotYetValidX509SecurityKey_Public, - ValidationFailureType.SigningKeyValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10248, - LogHelper.MarkAsNonPII(utcNotYetValid), - LogHelper.MarkAsNonPII(utcNow)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidSigningKey)) + Result = new TokenValidationError( + ValidationErrorType.SecurityTokenInvalidSigningKey, + new MessageDetail( + LogMessages.IDX10248, + LogHelper.MarkAsNonPII(utcNotYetValid), + LogHelper.MarkAsNonPII(utcNow)), + null), }, new SigningKeyValidationTheoryData { @@ -143,12 +137,10 @@ public static TheoryData SigningKeyValidationTes SecurityKey = null, SecurityToken = new JwtSecurityToken(), ValidationParameters = new ValidationParameters (), - SigningKeyValidationResult = new SigningKeyValidationResult( - null, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail(LogMessages.IDX10253), - ExceptionDetail.ExceptionType.ArgumentNull)) + Result = new TokenValidationError( + ValidationErrorType.ArgumentNull, + new MessageDetail(LogMessages.IDX10253), + null), }, }; @@ -162,6 +154,6 @@ public class SigningKeyValidationTheoryData : TheoryDataBase public SecurityToken SecurityToken { get; set; } internal ValidationParameters ValidationParameters { get; set; } public BaseConfiguration BaseConfiguration { get; set; } - internal SigningKeyValidationResult SigningKeyValidationResult { get; set; } + internal Result Result { get; set; } } } From 196daed8c124781f7112838fdd6f8f7678032db4 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Fri, 23 Aug 2024 14:43:26 +0100 Subject: [PATCH 12/32] Replaced TokenValidationError with ExceptionDetails. Added stack frames to failures, added initial cache experiment for stack frames --- .../JsonWebTokenHandler.DecryptToken.cs | 38 +++--- .../JsonWebTokenHandler.ReadToken.cs | 16 ++- .../JsonWebTokenHandler.ValidateSignature.cs | 118 ++++++++++-------- ...nWebTokenHandler.ValidateToken.Internal.cs | 96 +++++++++----- .../JwtTokenUtilities.DecryptTokenResult.cs | 18 ++- .../JwtTokenUtilities.cs | 24 ++-- .../Delegates.cs | 2 +- .../Results/Details/ExceptionDetail.cs | 37 ++++-- .../Results/TokenValidationError.cs | 2 +- .../Validation/Results/ValidationResult.cs | 13 +- .../Validation/ValidationParameters.cs | 2 +- .../Validation/Validators.Algorithm.cs | 19 +-- .../Validation/Validators.Audience.cs | 25 ++-- .../Validation/Validators.Issuer.cs | 31 +++-- .../Validation/Validators.IssuerSigningKey.cs | 37 +++--- .../Validation/Validators.Lifetime.cs | 33 ++--- .../Validation/Validators.TokenReplay.cs | 31 +++-- .../Validation/Validators.TokenType.cs | 25 ++-- .../AlgorithmValidationResultTests.cs | 36 +++--- 19 files changed, 357 insertions(+), 246 deletions(-) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs index 5e14e25a75..6be66b4d52 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using Microsoft.IdentityModel.Abstractions; @@ -23,37 +24,41 @@ public partial class JsonWebTokenHandler : TokenHandler /// The to be used for validating the token. /// /// The decoded / cleartext contents of the JWE. - internal Result DecryptToken( + internal Result DecryptToken( JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration configuration, CallContext? callContext) { if (jwtToken == null) - return TokenValidationErrorCommon.NullParameter(nameof(jwtToken)); + return ExceptionDetail.NullParameter( + nameof(jwtToken), + new StackFrame(true)); if (validationParameters == null) - return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); + return ExceptionDetail.NullParameter( + nameof(validationParameters), + new StackFrame(true)); if (string.IsNullOrEmpty(jwtToken.Enc)) - return new TokenValidationError( - ValidationErrorType.SecurityTokenDecryptionFailed, + return new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10612), - null); + ValidationErrorType.SecurityTokenDecryptionFailed, + new StackFrame(true)); - (IList? contentEncryptionKeys, TokenValidationError? validationError) result = + (IList? contentEncryptionKeys, ExceptionDetail? exceptionDetail) result = GetContentEncryptionKeys(jwtToken, validationParameters, configuration, callContext); - if (result.validationError != null) - return result.validationError; + if (result.exceptionDetail != null) + return result.exceptionDetail; if (result.contentEncryptionKeys == null) - return new TokenValidationError( - ValidationErrorType.SecurityTokenKeyWrap, + return new ExceptionDetail( new MessageDetail( TokenLogMessages.IDX10609, LogHelper.MarkAsSecurityArtifact(jwtToken, JwtTokenUtilities.SafeLogJwtToken)), - null); + ValidationErrorType.SecurityTokenKeyWrap, + new StackFrame(true)); return JwtTokenUtilities.DecryptJwtToken( jwtToken, @@ -67,7 +72,7 @@ internal Result DecryptToken( callContext); } - internal (IList?, TokenValidationError?) GetContentEncryptionKeys(JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration configuration, CallContext? callContext) + internal (IList?, ExceptionDetail?) GetContentEncryptionKeys(JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration configuration, CallContext? callContext) { IList? keys = null; @@ -184,16 +189,17 @@ internal Result DecryptToken( return (unwrappedKeys, null); else { - TokenValidationError tokenValidationError = new( - ValidationErrorType.SecurityTokenKeyWrap, + ExceptionDetail exceptionDetail = new( new MessageDetail( TokenLogMessages.IDX10618, keysAttempted?.ToString() ?? "", exceptionStrings?.ToString() ?? "", LogHelper.MarkAsSecurityArtifact(jwtToken, JwtTokenUtilities.SafeLogJwtToken)), + ValidationErrorType.SecurityTokenKeyWrap, + new System.Diagnostics.StackFrame(), null); - return (null, tokenValidationError); + return (null, exceptionDetail); } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs index 886b916ee6..a98657899d 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Diagnostics; using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Tokens; @@ -20,14 +21,16 @@ public partial class JsonWebTokenHandler : TokenHandler /// returned if is null or empty. /// returned if the validationParameters.TokenReader delegate is not able to parse/read the token as a valid . /// returned if is not a valid JWT, . - internal static Result ReadToken( + internal static Result ReadToken( string token, #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging CallContext? callContext) #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging { if (String.IsNullOrEmpty(token)) - return TokenValidationErrorCommon.NullParameter(nameof(token)); + return ExceptionDetail.NullParameter( + nameof(token), + new StackFrame(true)); try { @@ -35,13 +38,14 @@ internal static Result ReadToken( return jsonWebToken; } #pragma warning disable CA1031 // Do not catch general exception types - catch + catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { - return new TokenValidationError( - ValidationErrorType.SecurityTokenMalformed, + return new ExceptionDetail( new MessageDetail(LogMessages.IDX14107), - null); + ValidationErrorType.SecurityTokenMalformed, + new StackFrame(true), + ex); } } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs index 7e2882da69..cd3a342bae 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using Microsoft.IdentityModel.Abstractions; @@ -16,6 +17,11 @@ namespace Microsoft.IdentityModel.JsonWebTokens /// This partial class contains methods and logic related to the validation of tokens' signatures. public partial class JsonWebTokenHandler : TokenHandler { + static internal class SignatureStackFrames + { + // Test StackFrame to validate caching solution. Need to add all the possible stack frames. + static internal StackFrame? NoKeysProvided; + } /// /// Validates the JWT signature. /// @@ -27,17 +33,21 @@ public partial class JsonWebTokenHandler : TokenHandler /// Returned by the default implementation if the token is not signed, or if the validation fails. /// Returned if the algorithm is not supported by the key. /// Returned if the key cannot be resolved. - internal static Result ValidateSignature( + internal static Result ValidateSignature( JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration? configuration, CallContext callContext) { if (jwtToken is null) - return TokenValidationErrorCommon.NullParameter(nameof(jwtToken)); + return ExceptionDetail.NullParameter( + nameof(jwtToken), + new StackFrame(true)); if (validationParameters is null) - return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); + return ExceptionDetail.NullParameter( + nameof(validationParameters), + new StackFrame(true)); // Delegate is set by the user, we call it and return the result. if (validationParameters.SignatureValidator is not null) @@ -45,14 +55,14 @@ internal static Result ValidateSignature( // If the user wants to accept unsigned tokens, they must implement the delegate. if (!jwtToken.IsSigned) - return new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidSignature, + return new ExceptionDetail( new MessageDetail( TokenLogMessages.IDX10504, LogHelper.MarkAsSecurityArtifact( jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - null); + ValidationErrorType.SecurityTokenInvalidSignature, + new StackFrame(true)); SecurityKey? key = null; if (validationParameters.IssuerSigningKeyResolver is not null) @@ -85,13 +95,16 @@ internal static Result ValidateSignature( if (validationParameters.TryAllIssuerSigningKeys) return ValidateSignatureUsingAllKeys(jwtToken, validationParameters, configuration, callContext); else - return new TokenValidationError( - ValidationErrorType.SecurityTokenSignatureKeyNotFound, + { + StackFrame stackFrame = SignatureStackFrames.NoKeysProvided ??= new StackFrame(true); + return new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10500), - null); + ValidationErrorType.SecurityTokenSignatureKeyNotFound, + stackFrame); + } } - private static Result ValidateSignatureUsingAllKeys( + private static Result ValidateSignatureUsingAllKeys( JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration? configuration, @@ -101,29 +114,29 @@ private static Result ValidateSignatureUsingA // 1. User specified delegate: IssuerSigningKeyResolver returned null // 2. ResolveIssuerSigningKey returned null // Try all the keys. This is the degenerate case, not concerned about perf. - (Result? configResult, bool configKidMatched, KeyMatchFailedResult? configFailedResult) = ValidateUsingKeys( + (Result? configResult, bool configKidMatched, KeyMatchFailedResult? configFailedResult) = ValidateUsingKeys( jwtToken, validationParameters, configuration?.SigningKeys, callContext); - if (configResult is Result unwrappedConfigResult) + if (configResult is Result unwrappedConfigResult) return unwrappedConfigResult; - (Result? vpResult, bool vpKidMatched, KeyMatchFailedResult? vpFailedResult) = ValidateUsingKeys( + (Result? vpResult, bool vpKidMatched, KeyMatchFailedResult? vpFailedResult) = ValidateUsingKeys( jwtToken, validationParameters, validationParameters.IssuerSigningKeys, callContext); - if (vpResult is Result unwrappedVpResult) + if (vpResult is Result unwrappedVpResult) return unwrappedVpResult; if (vpFailedResult is null && configFailedResult is null) // No keys were attempted - return new TokenValidationError( - ValidationErrorType.SecurityTokenSignatureKeyNotFound, + return new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10500), - null); + ValidationErrorType.SecurityTokenSignatureKeyNotFound, + new StackFrame(true)); StringBuilder exceptionStrings = new(); StringBuilder keysAttempted = new(); @@ -145,7 +158,7 @@ private static Result ValidateSignatureUsingA kidMatched); } - private static (Result? validResult, bool KidMatched, KeyMatchFailedResult? failedResult) ValidateUsingKeys( + private static (Result? validResult, bool KidMatched, KeyMatchFailedResult? failedResult) ValidateUsingKeys( JsonWebToken jwtToken, ValidationParameters validationParameters, ICollection? keys, @@ -160,12 +173,12 @@ private static (Result? validResult, bool Kid bool kidExists = !string.IsNullOrEmpty(jwtToken.Kid); bool kidMatched = false; IList? keysAttempted = null; - IList? errors = null; + IList? errors = null; for (int i = 0; i < keysList.Count; i++) { SecurityKey key = keysList[i]; - Result result = ValidateSignatureWithKey(jwtToken, key, validationParameters, callContext); + Result result = ValidateSignatureWithKey(jwtToken, key, validationParameters, callContext); if (result.IsSuccess) { jwtToken.SigningKey = key; @@ -189,7 +202,7 @@ private static (Result? validResult, bool Kid return (null, kidMatched, null); } - private static Result ValidateSignatureWithKey( + private static Result ValidateSignatureWithKey( JsonWebToken jsonWebToken, SecurityKey key, ValidationParameters validationParameters, @@ -198,16 +211,16 @@ private static Result ValidateSignatureWithKe CryptoProviderFactory cryptoProviderFactory = validationParameters.CryptoProviderFactory ?? key.CryptoProviderFactory; if (!cryptoProviderFactory.IsSupportedAlgorithm(jsonWebToken.Alg, key)) { - return new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAlgorithm, + return new ExceptionDetail( new MessageDetail( - LogMessages.IDX14000, + TokenLogMessages.IDX10400, LogHelper.MarkAsNonPII(jsonWebToken.Alg), key), - null); + ValidationErrorType.SecurityTokenInvalidAlgorithm, + new StackFrame(true)); } - Result result = validationParameters.AlgorithmValidator( + Result result = validationParameters.AlgorithmValidator( jsonWebToken.Alg, key, jsonWebToken, @@ -221,13 +234,13 @@ private static Result ValidateSignatureWithKe try { if (signatureProvider == null) - return new TokenValidationError( - ValidationErrorType.InvalidOperation, + return new ExceptionDetail( new MessageDetail( TokenLogMessages.IDX10636, key?.ToString() ?? "Null", LogHelper.MarkAsNonPII(jsonWebToken.Alg)), - null); + ValidationErrorType.InvalidOperation, + new StackFrame(true)); bool valid = EncodingUtils.PerformEncodingDependentOperation( jsonWebToken.EncodedToken, @@ -242,27 +255,28 @@ private static Result ValidateSignatureWithKe if (valid) return key; else - return new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidSignature, + return new ExceptionDetail( new MessageDetail( TokenLogMessages.IDX10504, LogHelper.MarkAsSecurityArtifact( jsonWebToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - null); + ValidationErrorType.SecurityTokenInvalidSignature, + new StackFrame(true)); } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { - return new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidSignature, - new MessageDetail( - TokenLogMessages.IDX10504, - LogHelper.MarkAsSecurityArtifact( - jsonWebToken.EncodedToken, - JwtTokenUtilities.SafeLogJwtToken)), - ex); + return new ExceptionDetail( + new MessageDetail( + TokenLogMessages.IDX10504, + LogHelper.MarkAsSecurityArtifact( + jsonWebToken.EncodedToken, + JwtTokenUtilities.SafeLogJwtToken)), + ValidationErrorType.SecurityTokenInvalidSignature, + new StackFrame(true), + ex); } finally { @@ -270,7 +284,7 @@ private static Result ValidateSignatureWithKe } } - private static TokenValidationError GetSignatureValidationError( + private static ExceptionDetail GetSignatureValidationError( JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration? configuration, @@ -290,8 +304,7 @@ private static TokenValidationError GetSignatureValidationError( JsonWebToken localJwtToken = jwtToken; // avoid closure on non-exceptional path bool isKidInTVP = keysInTokenValidationParameters.Any(x => x.KeyId.Equals(localJwtToken.Kid)); string keyLocation = isKidInTVP ? "TokenValidationParameters" : "Configuration"; - return new TokenValidationError( - ValidationErrorType.SecurityTokenSignatureKeyNotFound, + return new ExceptionDetail( new MessageDetail( TokenLogMessages.IDX10511, LogHelper.MarkAsNonPII(keysAttempted.ToString()), @@ -301,12 +314,12 @@ private static TokenValidationError GetSignatureValidationError( LogHelper.MarkAsNonPII(jwtToken.Kid), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - null); + ValidationErrorType.SecurityTokenSignatureKeyNotFound, + new StackFrame(true)); } if (kidExists) - return new TokenValidationError( - ValidationErrorType.SecurityTokenSignatureKeyNotFound, + return new ExceptionDetail( new MessageDetail( TokenLogMessages.IDX10503, LogHelper.MarkAsNonPII(jwtToken.Kid), @@ -315,10 +328,10 @@ private static TokenValidationError GetSignatureValidationError( LogHelper.MarkAsNonPII(numKeysInConfiguration), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - null); + ValidationErrorType.SecurityTokenSignatureKeyNotFound, + new StackFrame(true)); - return new TokenValidationError( - ValidationErrorType.SecurityTokenSignatureKeyNotFound, + return new ExceptionDetail( new MessageDetail( TokenLogMessages.IDX10517, // Kid is missing and no keys match. LogHelper.MarkAsNonPII(keysAttempted.ToString()), @@ -326,7 +339,8 @@ private static TokenValidationError GetSignatureValidationError( LogHelper.MarkAsNonPII(numKeysInConfiguration), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - null); + ValidationErrorType.SecurityTokenSignatureKeyNotFound, + new StackFrame(true)); } private static void PopulateFailedResults( @@ -345,10 +359,10 @@ private static void PopulateFailedResults( } private struct KeyMatchFailedResult( - IList failedResults, + IList failedResults, IList keysAttempted) { - public IList FailedResults = failedResults; + public IList FailedResults = failedResults; public IList KeysAttempted = keysAttempted; } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs index e3f56bbce3..032d0c244a 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -15,6 +16,11 @@ namespace Microsoft.IdentityModel.JsonWebTokens { public partial class JsonWebTokenHandler : TokenHandler { + internal static class StackFrames + { + // Test StackFrame to validate caching solution. Need to add all the possible stack frames. + internal static StackFrame SignatureValidationFailed; + } /// /// Validates a token. /// On a validation failure, no exception will be thrown; instead, the exception will be set in the returned TokenValidationResult.Exception property. @@ -45,26 +51,33 @@ internal async Task ValidateTokenAsync( null, this, validationParameters, - TokenValidationErrorCommon.NullParameter(nameof(token))); + ExceptionDetail.NullParameter( + nameof(token), + new StackFrame(true))); if (validationParameters is null) return new ValidationResult( null, this, validationParameters, - TokenValidationErrorCommon.NullParameter(nameof(validationParameters))); + ExceptionDetail.NullParameter( + nameof(validationParameters), + new StackFrame(true))); if (token.Length > MaximumTokenSizeInBytes) return new ValidationResult( null, this, validationParameters, - new TokenValidationError( + new ExceptionDetail( + new MessageDetail( + TokenLogMessages.IDX10209, + LogHelper.MarkAsNonPII(token.Length), + LogHelper.MarkAsNonPII(MaximumTokenSizeInBytes)), ValidationErrorType.InvalidArgument, - new MessageDetail(TokenLogMessages.IDX10209, LogHelper.MarkAsNonPII(token.Length), LogHelper.MarkAsNonPII(MaximumTokenSizeInBytes)), - null)); + new StackFrame(true))); - Result result = ReadToken(token, callContext); + Result result = ReadToken(token, callContext); if (result.IsSuccess) return await ValidateTokenAsync( result.UnwrapResult(), @@ -77,7 +90,8 @@ internal async Task ValidateTokenAsync( null, this, validationParameters, - result.UnwrapError()); + result.UnwrapError(), + new StackFrame(true)); } /// @@ -92,24 +106,28 @@ internal async Task ValidateTokenAsync( token, this, validationParameters, - TokenValidationErrorCommon.NullParameter(nameof(token))); + ExceptionDetail.NullParameter( + nameof(token), + new StackFrame(true))); if (validationParameters is null) return new ValidationResult( token, this, validationParameters, - TokenValidationErrorCommon.NullParameter(nameof(validationParameters))); + ExceptionDetail.NullParameter( + nameof(validationParameters), + new StackFrame(true))); if (token is not JsonWebToken jwt) return new ValidationResult( token, this, validationParameters, - new TokenValidationError( - ValidationErrorType.InvalidArgument, + new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10001, nameof(token), nameof(JsonWebToken)), - null)); + ValidationErrorType.InvalidArgument, + new StackFrame(true))); return await InternalValidateTokenAsync( jwt, @@ -155,7 +173,7 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration, return result; } - if (TokenUtilities.IsRecoverableErrorType(result.TokenValidationError?.ErrorType)) + if (TokenUtilities.IsRecoverableErrorType(result.ExceptionDetail?.Type)) { // If we were still unable to validate, attempt to refresh the configuration and validate using it // but ONLY if the currentConfiguration is not null. We want to avoid refreshing the configuration on @@ -187,7 +205,7 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration, { validationParameters.RefreshBeforeValidation = false; validationParameters.ValidateWithLKG = true; - ValidationErrorType recoverableExceptionType = result.TokenValidationError?.ErrorType ?? ValidationErrorType.Unknown; + ValidationErrorType recoverableExceptionType = result.ExceptionDetail?.Type ?? ValidationErrorType.Unknown; BaseConfiguration[] validConfigurations = validationParameters.ConfigurationManager.GetValidLkgConfigurations(); for (int i = 0; i < validConfigurations.Length; i++) @@ -217,13 +235,13 @@ private async ValueTask ValidateJWEAsync( CallContext callContext, CancellationToken? cancellationToken) { - Result decryptionResult = DecryptToken( + Result decryptionResult = DecryptToken( jwtToken, validationParameters, configuration, callContext); if (!decryptionResult.IsSuccess) return new ValidationResult(jwtToken, this, validationParameters, decryptionResult.UnwrapError()); - Result readResult = ReadToken(decryptionResult.UnwrapResult(), callContext); + Result readResult = ReadToken(decryptionResult.UnwrapResult(), callContext); if (!readResult.IsSuccess) return new ValidationResult(jwtToken, this, validationParameters, readResult.UnwrapError()); @@ -253,40 +271,44 @@ private async ValueTask ValidateJWSAsync( DateTime? expires = jsonWebToken.HasPayloadClaim(JwtRegisteredClaimNames.Exp) ? jsonWebToken.ValidTo : null; DateTime? notBefore = jsonWebToken.HasPayloadClaim(JwtRegisteredClaimNames.Nbf) ? jsonWebToken.ValidFrom : null; - Result lifetimeValidationResult = validationParameters.LifetimeValidator( + Result lifetimeValidationResult = validationParameters.LifetimeValidator( notBefore, expires, jsonWebToken, validationParameters, callContext); if (!lifetimeValidationResult.IsSuccess) - return new ValidationResult(jsonWebToken, this, validationParameters, lifetimeValidationResult.UnwrapError()); + return new ValidationResult( + jsonWebToken, this, validationParameters, lifetimeValidationResult.UnwrapError(), new StackFrame(true)); if (jsonWebToken.Audiences is not IList tokenAudiences) tokenAudiences = jsonWebToken.Audiences.ToList(); - Result audienceValidationResult = validationParameters.AudienceValidator( + Result audienceValidationResult = validationParameters.AudienceValidator( tokenAudiences, jsonWebToken, validationParameters, callContext); if (!audienceValidationResult.IsSuccess) - return new ValidationResult(jsonWebToken, this, validationParameters, audienceValidationResult.UnwrapError()) + return new ValidationResult( + jsonWebToken, this, validationParameters, audienceValidationResult.UnwrapError(), new StackFrame(true)) { ValidatedLifetime = lifetimeValidationResult.UnwrapResult() }; - Result issuerValidationResult = await validationParameters.IssuerValidatorAsync( + Result issuerValidationResult = await validationParameters.IssuerValidatorAsync( jsonWebToken.Issuer, jsonWebToken, validationParameters, callContext, cancellationToken) .ConfigureAwait(false); if (!issuerValidationResult.IsSuccess) - return new ValidationResult(jsonWebToken, this, validationParameters, issuerValidationResult.UnwrapError()) + return new ValidationResult( + jsonWebToken, this, validationParameters, issuerValidationResult.UnwrapError(), new StackFrame(true)) { ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), ValidatedAudience = audienceValidationResult.UnwrapResult() }; - Result replayValidationResult = validationParameters.TokenReplayValidator( + Result replayValidationResult = validationParameters.TokenReplayValidator( expires, jsonWebToken.EncodedToken, validationParameters, callContext); if (!replayValidationResult.IsSuccess) - return new ValidationResult(jsonWebToken, this, validationParameters, replayValidationResult.UnwrapError()) + return new ValidationResult( + jsonWebToken, this, validationParameters, replayValidationResult.UnwrapError(), new StackFrame(true)) { ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), ValidatedAudience = audienceValidationResult.UnwrapResult(), @@ -297,9 +319,10 @@ private async ValueTask ValidateJWSAsync( // actor validation if (validationParameters.ValidateActor && !string.IsNullOrWhiteSpace(jsonWebToken.Actor)) { - Result actorReadingResult = ReadToken(jsonWebToken.Actor, callContext); + Result actorReadingResult = ReadToken(jsonWebToken.Actor, callContext); if (!actorReadingResult.IsSuccess) - return new ValidationResult(jsonWebToken, this, validationParameters, actorReadingResult.UnwrapError()) + return new ValidationResult( + jsonWebToken, this, validationParameters, actorReadingResult.UnwrapError(), new StackFrame(true)) { ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), ValidatedAudience = audienceValidationResult.UnwrapResult(), @@ -316,7 +339,8 @@ await ValidateJWSAsync(actorToken, actorParameters, configuration, callContext, // Consider adding a new ValidationResult type for actor validation // that wraps the actorValidationResult.ValidationResults if (!actorValidationResult.IsValid) - return new ValidationResult(jsonWebToken, this, validationParameters, actorValidationResult.TokenValidationError) + return new ValidationResult( + jsonWebToken, this, validationParameters, actorValidationResult.ExceptionDetail, new StackFrame(true)) { ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), ValidatedAudience = audienceValidationResult.UnwrapResult(), @@ -326,7 +350,7 @@ await ValidateJWSAsync(actorToken, actorParameters, configuration, callContext, }; } - Result typeValidationResult = validationParameters.TypeValidator( + Result typeValidationResult = validationParameters.TypeValidator( jsonWebToken.Typ, jsonWebToken, validationParameters, callContext); if (!typeValidationResult.IsSuccess) @@ -340,11 +364,14 @@ await ValidateJWSAsync(actorToken, actorParameters, configuration, callContext, }; // The signature validation delegate is yet to be migrated to ValidationParameters. - Result signatureValidationResult = ValidateSignature( + Result signatureValidationResult = ValidateSignature( jsonWebToken, validationParameters, configuration, callContext); if (!signatureValidationResult.IsSuccess) - return new ValidationResult(jsonWebToken, this, validationParameters, signatureValidationResult.UnwrapError()) + { + StackFrame stackFrame = StackFrames.SignatureValidationFailed ??= new StackFrame(true); + return new ValidationResult( + jsonWebToken, this, validationParameters, signatureValidationResult.UnwrapError(), stackFrame) { ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), ValidatedAudience = audienceValidationResult.UnwrapResult(), @@ -353,12 +380,15 @@ await ValidateJWSAsync(actorToken, actorParameters, configuration, callContext, ActorValidationResult = actorValidationResult, ValidatedTokenType = typeValidationResult.UnwrapResult() }; + } - Result issuerSigningKeyValidationResult = validationParameters.IssuerSigningKeyValidator( - signatureValidationResult.UnwrapResult(), jsonWebToken, validationParameters, configuration, callContext); + Result issuerSigningKeyValidationResult = + validationParameters.IssuerSigningKeyValidator( + signatureValidationResult.UnwrapResult(), jsonWebToken, validationParameters, configuration, callContext); if (!issuerSigningKeyValidationResult.IsSuccess) - return new ValidationResult(jsonWebToken, this, validationParameters, issuerSigningKeyValidationResult.UnwrapError()) + return new ValidationResult( + jsonWebToken, this, validationParameters, issuerSigningKeyValidationResult.UnwrapError(), new StackFrame(true)) { ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), ValidatedAudience = audienceValidationResult.UnwrapResult(), diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs index b074023a7b..19334194f1 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Diagnostics; using System.Text; using Microsoft.IdentityModel.Tokens; //using Microsoft.IdentityModel.Logging; @@ -20,17 +21,21 @@ public partial class JwtTokenUtilities /// The decryption parameters container. /// The call context used for logging. /// The decrypted, and if the 'zip' claim is set, decompressed string representation of the token. - internal static Result DecryptJwtToken( + internal static Result DecryptJwtToken( JsonWebToken jsonWebToken, ValidationParameters validationParameters, JwtTokenDecryptionParameters decryptionParameters, CallContext callContext) { if (validationParameters == null) - return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); + return ExceptionDetail.NullParameter( + nameof(validationParameters), + new StackFrame(true)); if (decryptionParameters == null) - return TokenValidationErrorCommon.NullParameter(nameof(decryptionParameters)); + return ExceptionDetail.NullParameter( + nameof(decryptionParameters), + new StackFrame(true)); bool decryptionSucceeded = false; bool algorithmNotSupportedByCryptoProvider = false; @@ -64,7 +69,7 @@ internal static Result DecryptJwtToken( continue; } - Result result = validationParameters.AlgorithmValidator(zipAlgorithm, key, jsonWebToken, validationParameters, callContext); + Result result = validationParameters.AlgorithmValidator(zipAlgorithm, key, jsonWebToken, validationParameters, callContext); if (!result.IsSuccess) { (exceptionStrings ??= new StringBuilder()).AppendLine(result.UnwrapError().MessageDetail.Message); @@ -117,9 +122,10 @@ internal static Result DecryptJwtToken( catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { - return new TokenValidationError( - ValidationErrorType.SecurityTokenDecompressionFailed, + return new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10679, zipAlgorithm), + ValidationErrorType.SecurityTokenDecompressionFailed, + new StackFrame(true), ex); } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs index f0928af793..335dbbd8dc 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics; using System.Globalization; using System.Security.Claims; using System.Security.Cryptography; @@ -331,14 +332,14 @@ internal static string DecryptJwtToken( if (!decryptionSucceeded) { - TokenValidationError error = GetDecryptionError( + ExceptionDetail exceptionDetail = GetDecryptionError( decryptionParameters, algorithmNotSupportedByCryptoProvider, exceptionStrings, keysAttempted, null); - throw LogHelper.LogExceptionMessage(ExceptionDetail.ExceptionFromType(error.ErrorType, error.MessageDetail, null)); + throw LogHelper.LogExceptionMessage(exceptionDetail.GetException()); } try @@ -354,7 +355,7 @@ internal static string DecryptJwtToken( } } - private static TokenValidationError GetDecryptionError( + private static ExceptionDetail GetDecryptionError( JwtTokenDecryptionParameters decryptionParameters, bool algorithmNotSupportedByCryptoProvider, StringBuilder exceptionStrings, @@ -364,29 +365,30 @@ private static TokenValidationError GetDecryptionError( #pragma warning restore CA1801 // Review unused parameters { if (keysAttempted is not null) - return new TokenValidationError( - ValidationErrorType.SecurityTokenDecryptionFailed, + return new ExceptionDetail( new MessageDetail( TokenLogMessages.IDX10603, keysAttempted.ToString(), exceptionStrings?.ToString() ?? string.Empty, LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken)), + ValidationErrorType.SecurityTokenDecryptionFailed, + new StackFrame(true), null); else if (algorithmNotSupportedByCryptoProvider) - return new TokenValidationError( - ValidationErrorType.SecurityTokenDecryptionFailed, + return new ExceptionDetail( new MessageDetail( TokenLogMessages.IDX10619, LogHelper.MarkAsNonPII(decryptionParameters.Alg), LogHelper.MarkAsNonPII(decryptionParameters.Enc)), - null); - else - return new TokenValidationError( ValidationErrorType.SecurityTokenDecryptionFailed, + new StackFrame(true)); + else + return new ExceptionDetail( new MessageDetail( TokenLogMessages.IDX10609, LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken)), - null); + ValidationErrorType.SecurityTokenDecryptionFailed, + new StackFrame(true)); } private static byte[] DecryptToken(CryptoProviderFactory cryptoProviderFactory, SecurityKey key, string encAlg, byte[] ciphertext, byte[] headerAscii, byte[] initializationVector, byte[] authenticationTag) diff --git a/src/Microsoft.IdentityModel.Tokens/Delegates.cs b/src/Microsoft.IdentityModel.Tokens/Delegates.cs index 491c497c28..485727f5c8 100644 --- a/src/Microsoft.IdentityModel.Tokens/Delegates.cs +++ b/src/Microsoft.IdentityModel.Tokens/Delegates.cs @@ -205,7 +205,7 @@ namespace Microsoft.IdentityModel.Tokens /// The to be used for logging. /// This method is not expected to throw. /// The validated . - internal delegate Result SignatureValidatorDelegate(SecurityToken token, ValidationParameters validationParameters, BaseConfiguration? configuration, CallContext? callContext); + internal delegate Result SignatureValidatorDelegate(SecurityToken token, ValidationParameters validationParameters, BaseConfiguration? configuration, CallContext? callContext); /// /// Transforms the security token before signature validation. diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs index 89b959f266..ba2e03ecf2 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs @@ -15,35 +15,48 @@ internal class ExceptionDetail /// /// Creates an instance of /// - /// contains information about the exception that is used to generate the exception message. - /// is the type of exception that occurred. - public ExceptionDetail(MessageDetail messageDetail, ValidationErrorType exceptionType) - : this(messageDetail, exceptionType, null) + /// contains information about the exception that is used to generate the exception message. + /// is the type of exception that occurred. + /// is the stack frame where the exception occurred. + public ExceptionDetail(MessageDetail messageDetail, ValidationErrorType exceptionType, StackFrame stackFrame) + : this(messageDetail, exceptionType, stackFrame, null) { } /// /// Creates an instance of /// - /// contains information about the exception that is used to generate the exception message. - /// is the type of exception that occurred. - /// is the inner exception that occurred. - public ExceptionDetail(MessageDetail messageDetail, ValidationErrorType exceptionType, Exception innerException) + /// contains information about the exception that is used to generate the exception message. + /// is the type of exception that occurred. + /// is the stack frame where the exception occurred. + /// is the inner exception that occurred. + public ExceptionDetail(MessageDetail messageDetail, ValidationErrorType exceptionType, StackFrame stackFrame, Exception innerException) { Type = exceptionType; InnerException = innerException; MessageDetail = messageDetail; + StackFrames = new List(4) + { + stackFrame + }; } /// /// Creates an instance of an using /// /// An instantance of an Exception. - public Exception GetException() => ExceptionFromType(Type, MessageDetail, InnerException); + public Exception GetException() + { + Exception exception = ExceptionFromType(Type, MessageDetail, InnerException); + if (exception is SecurityTokenException securityTokenException) + securityTokenException.ExceptionDetail = this; + + return exception; + } - internal static ExceptionDetail NullParameter(string parameterName) => new ExceptionDetail( + internal static ExceptionDetail NullParameter(string parameterName, StackFrame stackFrame) => new ExceptionDetail( MessageDetail.NullParameter(parameterName), - ValidationErrorType.ArgumentNull); + ValidationErrorType.ArgumentNull, stackFrame); /// /// Gets the type of exception that occurred. @@ -63,7 +76,7 @@ public ExceptionDetail(MessageDetail messageDetail, ValidationErrorType exceptio /// /// Gets the stack frames where the exception occurred. /// - public IList StackFrames { get; } = []; + public IList StackFrames { get; } public static Exception ExceptionFromType( ValidationErrorType exceptionType, diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs index 4abfd765ce..e9683beff9 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs @@ -36,7 +36,7 @@ public TokenValidationError( if (AppContextSwitches.DontFailOnMissingTid) CallerLineNumber = 123; - _stackFrame = new StackFrame(); + _stackFrame = new StackFrame(true); } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs index ceb6ed2cc9..fc1a8a4577 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs @@ -3,6 +3,7 @@ #nullable enable using System; +using System.Diagnostics; namespace Microsoft.IdentityModel.Tokens { @@ -33,22 +34,26 @@ public ValidationResult( SecurityToken? securityToken, TokenHandler tokenHandler, ValidationParameters? validationParameters, - TokenValidationError tokenValidationError) + ExceptionDetail exceptionDetail, + StackFrame? stackFrame = null) { TokenHandler = tokenHandler ?? throw new ArgumentNullException("TokenHandler cannot be null."); SecurityToken = securityToken; ValidationParameters = validationParameters; - TokenValidationError = tokenValidationError; + ExceptionDetail = exceptionDetail; IsValid = false; + + if (stackFrame != null) + ExceptionDetail.StackFrames.Add(stackFrame); } + public ExceptionDetail? ExceptionDetail { get; private set; } + /// /// True if the token was successfully validated, false otherwise. /// public bool IsValid { get; private set; } - public TokenValidationError? TokenValidationError { get; private set; } - /// /// Logs the validation result. /// diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs b/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs index e993f914f7..5e612cdd82 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs @@ -495,7 +495,7 @@ public TokenReplayValidatorDelegate TokenReplayValidator /// /// Allows overriding the delegate that will be used to validate the type of the token. - /// If the token type cannot be validated, a MUST be returned by the delegate. + /// If the token type cannot be validated, a MUST be returned by the delegate. /// Note: the 'type' parameter may be null if it couldn't be extracted from its usual location. /// Implementations that need to resolve it from a different location can use the 'token' parameter. /// diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs index 69673f2fb9..a3c4cbc006 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Diagnostics; using System.Linq; using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; @@ -19,7 +20,7 @@ namespace Microsoft.IdentityModel.Tokens /// /// A that contains the results of validating the algorithm. /// This delegate is not expected to throw. - internal delegate Result AlgorithmValidatorDelegate( + internal delegate Result AlgorithmValidatorDelegate( string algorithm, SecurityKey securityKey, SecurityToken securityToken, @@ -37,7 +38,7 @@ public static partial class Validators /// required for validation. /// #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging - internal static Result ValidateAlgorithm( + internal static Result ValidateAlgorithm( string algorithm, SecurityKey securityKey, SecurityToken securityToken, @@ -46,15 +47,19 @@ internal static Result ValidateAlgorithm( #pragma warning restore CA1801 // TODO: remove pragma disable once callContext is used for logging { if (validationParameters == null) - return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); + return ExceptionDetail.NullParameter( + nameof(validationParameters), + new StackFrame(true)); - if (validationParameters.ValidAlgorithms != null && validationParameters.ValidAlgorithms.Count > 0 && !validationParameters.ValidAlgorithms.Contains(algorithm, StringComparer.Ordinal)) - return new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAlgorithm, + if (validationParameters.ValidAlgorithms != null && + validationParameters.ValidAlgorithms.Count > 0 && + !validationParameters.ValidAlgorithms.Contains(algorithm, StringComparer.Ordinal)) + return new ExceptionDetail( new MessageDetail( LogMessages.IDX10696, LogHelper.MarkAsNonPII(algorithm)), - null); + ValidationErrorType.SecurityTokenInvalidAlgorithm, + new StackFrame(true)); return algorithm; } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs index 74ee278ded..98a2a649a3 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; @@ -18,7 +19,7 @@ namespace Microsoft.IdentityModel.Tokens /// /// A that contains the results of validating the issuer. /// This delegate is not expected to throw. - internal delegate Result AudienceValidatorDelegate( + internal delegate Result AudienceValidatorDelegate( IList audiences, SecurityToken? securityToken, ValidationParameters validationParameters, @@ -42,32 +43,36 @@ public static partial class Validators /// If none of the 'audiences' matched either or one of . /// An EXACT match is required. #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging - internal static Result ValidateAudience(IList tokenAudiences, SecurityToken? securityToken, ValidationParameters validationParameters, CallContext callContext) + internal static Result ValidateAudience(IList tokenAudiences, SecurityToken? securityToken, ValidationParameters validationParameters, CallContext callContext) #pragma warning restore CA1801 { if (validationParameters == null) - return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); + return ExceptionDetail.NullParameter( + nameof(validationParameters), + new StackFrame(true)); if (tokenAudiences == null) - return TokenValidationErrorCommon.NullParameter(nameof(tokenAudiences)); + return ExceptionDetail.NullParameter( + nameof(tokenAudiences), + new StackFrame(true)); if (tokenAudiences.Count == 0) - return new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + return new ExceptionDetail( new MessageDetail(LogMessages.IDX10206), - null); + ValidationErrorType.SecurityTokenInvalidAudience, + new StackFrame(true)); string? validAudience = ValidTokenAudience(tokenAudiences, validationParameters.ValidAudiences, validationParameters.IgnoreTrailingSlashWhenValidatingAudience); if (validAudience != null) return validAudience; - return new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + return new ExceptionDetail( new MessageDetail( LogMessages.IDX10215, LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(tokenAudiences)), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidAudiences))), - null); + ValidationErrorType.SecurityTokenInvalidAudience, + new StackFrame(true)); } private static string? ValidTokenAudience(IList tokenAudiences, IList validAudiences, bool ignoreTrailingSlashWhenValidatingAudience) diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs index e3e5957d01..e9d49beff7 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using Microsoft.IdentityModel.Abstractions; @@ -30,7 +31,7 @@ internal record struct ValidatedIssuer(string Issuer, IssuerValidationSource Val /// /// An that contains the results of validating the issuer. /// This delegate is not expected to throw. - internal delegate Task> IssuerValidationDelegateAsync( + internal delegate Task> IssuerValidationDelegateAsync( string issuer, SecurityToken securityToken, ValidationParameters validationParameters, @@ -52,7 +53,7 @@ public static partial class Validators /// /// An that contains either the issuer that was validated or an error. /// An EXACT match is required. - internal static async Task> ValidateIssuerAsync( + internal static async Task> ValidateIssuerAsync( string issuer, SecurityToken securityToken, ValidationParameters validationParameters, @@ -63,17 +64,21 @@ internal static async Task> Valida { if (string.IsNullOrWhiteSpace(issuer)) { - return new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidIssuer, + return new ExceptionDetail( new MessageDetail(LogMessages.IDX10211), - null); + ValidationErrorType.SecurityTokenInvalidIssuer, + new StackFrame(true)); } if (validationParameters == null) - return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); + return ExceptionDetail.NullParameter( + nameof(validationParameters), + new StackFrame(true)); if (securityToken == null) - return TokenValidationErrorCommon.NullParameter(nameof(securityToken)); + return ExceptionDetail.NullParameter( + nameof(securityToken), + new StackFrame(true)); BaseConfiguration? configuration = null; if (validationParameters.ConfigurationManager != null) @@ -81,10 +86,10 @@ internal static async Task> Valida // Return failed IssuerValidationResult if all possible places to validate against are null or empty. if (validationParameters.ValidIssuers.Count == 0 && string.IsNullOrWhiteSpace(configuration?.Issuer)) - return new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidIssuer, + return new ExceptionDetail( new MessageDetail(LogMessages.IDX10211), - null); + ValidationErrorType.SecurityTokenInvalidIssuer, + new StackFrame(true)); if (configuration != null) { @@ -126,14 +131,14 @@ internal static async Task> Valida } } - return new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidIssuer, + return new ExceptionDetail( new MessageDetail( LogMessages.IDX10212, LogHelper.MarkAsNonPII(issuer), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidIssuers)), LogHelper.MarkAsNonPII(configuration?.Issuer)), - null); + ValidationErrorType.SecurityTokenInvalidIssuer, + new StackFrame(true)); } } #nullable restore diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs index abd9359f75..389633fe7a 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs @@ -2,10 +2,9 @@ // Licensed under the MIT License. using System; +using System.Diagnostics; using System.Security.Cryptography.X509Certificates; using Microsoft.IdentityModel.Abstractions; - -//using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; #nullable enable @@ -23,7 +22,7 @@ internal record struct ValidatedSigningKeyLifetime(DateTime? ValidFrom, DateTime /// The to be used for logging. /// A that contains the results of validating the issuer. /// This delegate is not expected to throw. - internal delegate Result IssuerSigningKeyValidatorDelegate( + internal delegate Result IssuerSigningKeyValidatorDelegate( SecurityKey signingKey, SecurityToken securityToken, ValidationParameters validationParameters, @@ -47,7 +46,7 @@ public static partial class Validators /// if 'securityKey' is null and ValidateIssuerSigningKey is true. /// if 'securityToken' is null and ValidateIssuerSigningKey is true. /// if 'validationParameters' is null. - internal static Result ValidateIssuerSigningKey( + internal static Result ValidateIssuerSigningKey( SecurityKey securityKey, SecurityToken securityToken, ValidationParameters validationParameters, @@ -57,18 +56,20 @@ internal static Result Valida CallContext? callContext) { if (validationParameters == null) - return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); + return ExceptionDetail.NullParameter( + nameof(validationParameters), + new StackFrame(true)); if (securityKey == null) - return new TokenValidationError( + return new ExceptionDetail( + new MessageDetail(LogMessages.IDX10253, nameof(securityKey)), ValidationErrorType.ArgumentNull, - new MessageDetail( - LogMessages.IDX10253, - nameof(securityKey)), - null); + new StackFrame(true)); if (securityToken == null) - return TokenValidationErrorCommon.NullParameter(nameof(securityToken)); + return ExceptionDetail.NullParameter( + nameof(securityToken), + new StackFrame(true)); return ValidateIssuerSigningKeyLifeTime(securityKey, validationParameters, callContext); } @@ -80,7 +81,7 @@ internal static Result Valida /// The to be used for validating the token. /// #pragma warning disable CA1801 // Review unused parameters - internal static Result ValidateIssuerSigningKeyLifeTime( + internal static Result ValidateIssuerSigningKeyLifeTime( SecurityKey securityKey, ValidationParameters validationParameters, CallContext? callContext) @@ -97,26 +98,26 @@ internal static Result Valida notAfterUtc = cert.NotAfter.ToUniversalTime(); if (notBeforeUtc > DateTimeUtil.Add(utcNow, validationParameters.ClockSkew)) - return new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidSigningKey, + return new ExceptionDetail( new MessageDetail( LogMessages.IDX10248, LogHelper.MarkAsNonPII(notBeforeUtc), LogHelper.MarkAsNonPII(utcNow)), - null); + ValidationErrorType.SecurityTokenInvalidSigningKey, + new StackFrame(true)); //TODO: Move to CallContext //if (LogHelper.IsEnabled(EventLogLevel.Informational)) // LogHelper.LogInformation(LogMessages.IDX10250, LogHelper.MarkAsNonPII(notBeforeUtc), LogHelper.MarkAsNonPII(utcNow)); if (notAfterUtc < DateTimeUtil.Add(utcNow, validationParameters.ClockSkew.Negate())) - return new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidSigningKey, + return new ExceptionDetail( new MessageDetail( LogMessages.IDX10249, LogHelper.MarkAsNonPII(notAfterUtc), LogHelper.MarkAsNonPII(utcNow)), - null); + ValidationErrorType.SecurityTokenInvalidSigningKey, + new StackFrame(true)); // TODO: Move to CallContext //if (LogHelper.IsEnabled(EventLogLevel.Informational)) diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs index ade4486592..4f3c8d84fe 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Diagnostics; using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; @@ -20,7 +21,7 @@ internal record struct ValidatedLifetime(DateTime? NotBefore, DateTime? Expires) /// /// A that contains the results of validating the issuer. /// This delegate is not expected to throw. - internal delegate Result LifetimeValidatorDelegate( + internal delegate Result LifetimeValidatorDelegate( DateTime? notBefore, DateTime? expires, SecurityToken? securityToken, @@ -48,7 +49,7 @@ public static partial class Validators /// If 'expires' is < DateTime.UtcNow. /// All time comparisons apply . #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging - internal static Result ValidateLifetime( + internal static Result ValidateLifetime( DateTime? notBefore, DateTime? expires, SecurityToken? securityToken, @@ -57,43 +58,45 @@ internal static Result ValidateLifetime #pragma warning restore CA1801 { if (validationParameters == null) - return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); + return ExceptionDetail.NullParameter( + nameof(validationParameters), + new StackFrame(true)); if (!expires.HasValue) - return new TokenValidationError( - ValidationErrorType.SecurityTokenNoExpiration, + return new ExceptionDetail( new MessageDetail( LogMessages.IDX10225, LogHelper.MarkAsNonPII(securityToken == null ? "null" : securityToken.GetType().ToString())), - null); + ValidationErrorType.SecurityTokenNoExpiration, + new StackFrame(true)); if (notBefore.HasValue && expires.HasValue && (notBefore.Value > expires.Value)) - return new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidLifetime, + return new ExceptionDetail( new MessageDetail( LogMessages.IDX10224, LogHelper.MarkAsNonPII(notBefore.Value), LogHelper.MarkAsNonPII(expires.Value)), - null); + ValidationErrorType.SecurityTokenInvalidLifetime, + new StackFrame(true)); DateTime utcNow = DateTime.UtcNow; if (notBefore.HasValue && (notBefore.Value > DateTimeUtil.Add(utcNow, validationParameters.ClockSkew))) - return new TokenValidationError( - ValidationErrorType.SecurityTokenNotYetValid, + return new ExceptionDetail( new MessageDetail( LogMessages.IDX10222, LogHelper.MarkAsNonPII(notBefore.Value), LogHelper.MarkAsNonPII(utcNow)), - null); + ValidationErrorType.SecurityTokenNotYetValid, + new StackFrame(true)); if (expires.HasValue && (expires.Value < DateTimeUtil.Add(utcNow, validationParameters.ClockSkew.Negate()))) - return new TokenValidationError( - ValidationErrorType.SecurityTokenExpired, + return new ExceptionDetail( new MessageDetail( LogMessages.IDX10223, LogHelper.MarkAsNonPII(expires.Value), LogHelper.MarkAsNonPII(utcNow)), - null); + ValidationErrorType.SecurityTokenExpired, + new StackFrame(true)); // if it reaches here, that means lifetime of the token is valid if (LogHelper.IsEnabled(EventLogLevel.Informational)) diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs index b279c10454..cf416c67a8 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Diagnostics; using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; @@ -16,7 +17,7 @@ namespace Microsoft.IdentityModel.Tokens /// /// A that contains the results of validating the token. /// This delegate is not expected to throw. - internal delegate Result TokenReplayValidatorDelegate( + internal delegate Result TokenReplayValidatorDelegate( DateTime? expirationTime, string securityToken, ValidationParameters validationParameters, @@ -40,41 +41,45 @@ public static partial class Validators /// If the 'securityToken' is found in the cache. /// If the 'securityToken' could not be added to the . #pragma warning disable CA1801 // Review unused parameters - internal static Result ValidateTokenReplay(DateTime? expirationTime, string securityToken, ValidationParameters validationParameters, CallContext callContext) + internal static Result ValidateTokenReplay(DateTime? expirationTime, string securityToken, ValidationParameters validationParameters, CallContext callContext) #pragma warning restore CA1801 // Review unused parameters { if (string.IsNullOrWhiteSpace(securityToken)) - return TokenValidationErrorCommon.NullParameter(nameof(securityToken)); + return ExceptionDetail.NullParameter( + nameof(securityToken), + new StackFrame(true)); if (validationParameters == null) - return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); + return ExceptionDetail.NullParameter( + nameof(validationParameters), + new StackFrame(true)); // check if token if replay cache is set, then there must be an expiration time. if (validationParameters.TokenReplayCache != null) { if (expirationTime == null) - return new TokenValidationError( - ValidationErrorType.SecurityTokenReplayDetected, + return new ExceptionDetail( new MessageDetail( LogMessages.IDX10227, LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), - null); + ValidationErrorType.SecurityTokenReplayDetected, + new StackFrame(true)); if (validationParameters.TokenReplayCache.TryFind(securityToken)) - return new TokenValidationError( - ValidationErrorType.SecurityTokenReplayDetected, + return new ExceptionDetail( new MessageDetail( LogMessages.IDX10228, LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), - null); + ValidationErrorType.SecurityTokenReplayDetected, + new StackFrame(true)); if (!validationParameters.TokenReplayCache.TryAdd(securityToken, expirationTime.Value)) - return new TokenValidationError( - ValidationErrorType.SecurityTokenReplayAddFailed, + return new ExceptionDetail( new MessageDetail( LogMessages.IDX10229, LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), - null); + ValidationErrorType.SecurityTokenReplayAddFailed, + new StackFrame(true)); } // if it reaches here, that means no token replay is detected. diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs index 4b54c085dd..1b43466145 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Diagnostics; using System.Linq; using Microsoft.IdentityModel.Abstractions; @@ -21,7 +22,7 @@ internal record struct ValidatedTokenType(string Type, int ValidTypeCount); /// /// A that contains the results of validating the token type. /// An EXACT match is required. (case sensitive) is used for comparing against . - internal delegate Result TypeValidatorDelegate( + internal delegate Result TypeValidatorDelegate( string? type, SecurityToken? securityToken, ValidationParameters validationParameters, @@ -39,7 +40,7 @@ public static partial class Validators /// A that contains the results of validating the token type. /// An EXACT match is required. (case sensitive) is used for comparing against . #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging - internal static Result ValidateTokenType( + internal static Result ValidateTokenType( string? type, SecurityToken? securityToken, ValidationParameters validationParameters, @@ -47,10 +48,14 @@ internal static Result ValidateTokenTy #pragma warning restore CA1801 // TODO: remove pragma disable once callContext is used for logging { if (securityToken == null) - return TokenValidationErrorCommon.NullParameter(nameof(securityToken)); + return ExceptionDetail.NullParameter( + nameof(securityToken), + new StackFrame(true)); if (validationParameters == null) - return TokenValidationErrorCommon.NullParameter(nameof(validationParameters)); + return ExceptionDetail.NullParameter( + nameof(validationParameters), + new StackFrame(true)); if (validationParameters.ValidTypes.Count == 0) { @@ -59,20 +64,20 @@ internal static Result ValidateTokenTy } if (string.IsNullOrEmpty(type)) - return new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidType, + return new ExceptionDetail( new MessageDetail(LogMessages.IDX10256), - null); + ValidationErrorType.SecurityTokenInvalidType, + new StackFrame(true)); if (!validationParameters.ValidTypes.Contains(type, StringComparer.Ordinal)) { - return new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidType, + return new ExceptionDetail( new MessageDetail( LogMessages.IDX10257, LogHelper.MarkAsNonPII(type), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidTypes))), - null); + ValidationErrorType.SecurityTokenInvalidType, + new StackFrame(true)); } // TODO: Move to CallContext diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs index 3e4a2efa1c..709da8b0a4 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs @@ -5,6 +5,7 @@ using Microsoft.IdentityModel.Logging; using Xunit; using Microsoft.IdentityModel.Abstractions; +using System; namespace Microsoft.IdentityModel.Tokens.Validation.Tests { @@ -15,7 +16,7 @@ public void ValidateAlgorithm(AlgorithmTheoryData theoryData) { CompareContext context = TestUtilities.WriteHeader($"{this}.AlgorithmValidationResultTests", theoryData); - Result result = Validators.ValidateAlgorithm( + Result result = Validators.ValidateAlgorithm( theoryData.Algorithm, theoryData.SecurityKey, theoryData.SecurityToken, @@ -23,21 +24,18 @@ public void ValidateAlgorithm(AlgorithmTheoryData theoryData) new CallContext()); if (result.IsSuccess) + { IdentityComparer.AreStringsEqual( result.UnwrapResult(), theoryData.Result.UnwrapResult(), context); + + theoryData.ExpectedException.ProcessNoException(); + } else { - IdentityComparer.AreTokenValidationErrorsEqual( - result.UnwrapError(), - theoryData.Result.UnwrapError(), - context); - - if (result.UnwrapError().InnerException is not null) - theoryData.ExpectedException.ProcessException(result.UnwrapError().InnerException); - else - theoryData.ExpectedException.ProcessNoException(); + Exception exception = result.UnwrapError().GetException(); + theoryData.ExpectedException.ProcessException(exception); } TestUtilities.AssertFailIfErrors(context); @@ -55,32 +53,36 @@ public static TheoryData AlgorithmValidationTestCases { TestId = "Invalid_ValidationParametersAreNull", Algorithm = null, + ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), SecurityKey = null, SecurityToken = null, ValidationParameters = null, - Result = new TokenValidationError( - ValidationErrorType.ArgumentNull, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), - null) + ValidationErrorType.ArgumentNull, + null, // StackFrame + null) // InnerException }, new AlgorithmTheoryData { TestId = "Invalid_ValidateAlgorithmNotAValidAlgorithm", Algorithm = SecurityAlgorithms.Sha256, + ExpectedException = ExpectedException.SecurityTokenInvalidAlgorithmException("IDX10696:"), SecurityKey = securityKey, SecurityToken = null, ValidationParameters = new ValidationParameters { ValidAlgorithms = new[] { SecurityAlgorithms.HmacSha256 } }, - Result = new TokenValidationError( - ValidationErrorType.ArgumentNull, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10696, LogHelper.MarkAsNonPII(SecurityAlgorithms.Sha256)), - null), + ValidationErrorType.SecurityTokenInvalidAlgorithm, + null, // StackFrame + null),// InnerException }, new AlgorithmTheoryData { @@ -120,7 +122,7 @@ public class AlgorithmTheoryData : TheoryDataBase internal ValidationParameters ValidationParameters { get; set; } - internal Result Result { get; set; } + internal Result Result { get; set; } } } } From 48dc149b73814b7355029c115cbb14325daf8afc Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Fri, 23 Aug 2024 14:55:59 +0100 Subject: [PATCH 13/32] Removed optionality from CancellationToken parameter --- .../JsonWebTokenHandler.ValidateToken.Internal.cs | 10 +++++----- .../Validation/Validators.Issuer.cs | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs index 032d0c244a..06a4f05666 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs @@ -43,7 +43,7 @@ internal async Task ValidateTokenAsync( string token, ValidationParameters validationParameters, CallContext callContext, - CancellationToken? cancellationToken) + CancellationToken cancellationToken) { // These exceptions will be removed once we add ExceptionDetails to TokenValidationResult. if (string.IsNullOrEmpty(token)) @@ -99,7 +99,7 @@ internal async Task ValidateTokenAsync( SecurityToken token, ValidationParameters validationParameters, CallContext callContext, - CancellationToken? cancellationToken) + CancellationToken cancellationToken) { if (token is null) return new ValidationResult( @@ -151,7 +151,7 @@ private async ValueTask InternalValidateTokenAsync( JsonWebToken jsonWebToken, ValidationParameters validationParameters, CallContext callContext, - CancellationToken? cancellationToken) + CancellationToken cancellationToken) { BaseConfiguration currentConfiguration = await GetCurrentConfigurationAsync(validationParameters) @@ -233,7 +233,7 @@ private async ValueTask ValidateJWEAsync( ValidationParameters validationParameters, BaseConfiguration configuration, CallContext callContext, - CancellationToken? cancellationToken) + CancellationToken cancellationToken) { Result decryptionResult = DecryptToken( jwtToken, validationParameters, configuration, callContext); @@ -266,7 +266,7 @@ private async ValueTask ValidateJWSAsync( ValidationParameters validationParameters, BaseConfiguration configuration, CallContext callContext, - CancellationToken? cancellationToken) + CancellationToken cancellationToken) { DateTime? expires = jsonWebToken.HasPayloadClaim(JwtRegisteredClaimNames.Exp) ? jsonWebToken.ValidTo : null; DateTime? notBefore = jsonWebToken.HasPayloadClaim(JwtRegisteredClaimNames.Nbf) ? jsonWebToken.ValidFrom : null; diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs index e9d49beff7..e3cbd9fcbe 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs @@ -36,7 +36,7 @@ internal delegate Task> IssuerValidatio SecurityToken securityToken, ValidationParameters validationParameters, CallContext callContext, - CancellationToken? cancellationToken); + CancellationToken cancellationToken); /// /// IssuerValidation @@ -60,7 +60,7 @@ internal static async Task> ValidateIss #pragma warning disable CA1801 // Review unused parameters CallContext? callContext, #pragma warning restore CA1801 // Review unused parameters - CancellationToken? cancellationToken) + CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(issuer)) { @@ -82,7 +82,7 @@ internal static async Task> ValidateIss BaseConfiguration? configuration = null; if (validationParameters.ConfigurationManager != null) - configuration = await validationParameters.ConfigurationManager.GetBaseConfigurationAsync(cancellationToken ?? CancellationToken.None).ConfigureAwait(false); + configuration = await validationParameters.ConfigurationManager.GetBaseConfigurationAsync(cancellationToken).ConfigureAwait(false); // Return failed IssuerValidationResult if all possible places to validate against are null or empty. if (validationParameters.ValidIssuers.Count == 0 && string.IsNullOrWhiteSpace(configuration?.Issuer)) From 93492ee7a33626257c9673d3c72254248f99b540 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Fri, 23 Aug 2024 16:58:52 +0100 Subject: [PATCH 14/32] Updated tests --- .../JsonWebTokenHandler.DecryptToken.cs | 4 +- .../Validation/Validators.Audience.cs | 5 +- .../JsonWebTokenHandler.DecryptTokenTests.cs | 106 ++++++--------- .../JsonWebTokenHandler.ReadTokenTests.cs | 76 +++++------ ...nWebTokenHandler.ValidateSignatureTests.cs | 127 +++++++++-------- .../IdentityComparer.cs | 22 +++ .../AlgorithmValidationResultTests.cs | 2 +- .../Validation/AsyncValidatorsTests.cs | 58 -------- .../AudienceValidationResultTests.cs | 128 +++++++++++------- .../Validation/ExceptionDetailsTests.cs | 56 ++++---- .../Validation/IssuerValidationResultTests.cs | 41 +++--- .../LifetimeValidationResultTests.cs | 60 ++++---- .../Validation/ReplayValidationResultTests.cs | 52 +++---- .../SigningKeyValidationResultTests.cs | 54 ++++---- .../TokenTypeValidationResultTests.cs | 104 +++++++------- .../Validation/ValidationParametersTests.cs | 2 +- 16 files changed, 457 insertions(+), 440 deletions(-) delete mode 100644 test/Microsoft.IdentityModel.Tokens.Tests/Validation/AsyncValidatorsTests.cs diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs index 6be66b4d52..67a1d1f45f 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs @@ -43,7 +43,7 @@ internal Result DecryptToken( if (string.IsNullOrEmpty(jwtToken.Enc)) return new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10612), - ValidationErrorType.SecurityTokenDecryptionFailed, + ValidationErrorType.SecurityToken, new StackFrame(true)); (IList? contentEncryptionKeys, ExceptionDetail? exceptionDetail) result = @@ -57,7 +57,7 @@ internal Result DecryptToken( new MessageDetail( TokenLogMessages.IDX10609, LogHelper.MarkAsSecurityArtifact(jwtToken, JwtTokenUtilities.SafeLogJwtToken)), - ValidationErrorType.SecurityTokenKeyWrap, + ValidationErrorType.SecurityTokenDecryptionFailed, new StackFrame(true)); return JwtTokenUtilities.DecryptJwtToken( diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs index 98a2a649a3..df57362fe8 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs @@ -52,8 +52,9 @@ internal static Result ValidateAudience(IList t new StackFrame(true)); if (tokenAudiences == null) - return ExceptionDetail.NullParameter( - nameof(tokenAudiences), + return new ExceptionDetail( + new MessageDetail(LogMessages.IDX10207), + ValidationErrorType.SecurityTokenInvalidAudience, new StackFrame(true)); if (tokenAudiences.Count == 0) diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.DecryptTokenTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.DecryptTokenTests.cs index 097acca16c..21846efd78 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.DecryptTokenTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.DecryptTokenTests.cs @@ -2,8 +2,8 @@ // Licensed under the MIT License. using System; -using System.Diagnostics; using System.IdentityModel.Tokens.Jwt.Tests; +using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.TestUtils; using Microsoft.IdentityModel.Tokens; @@ -30,29 +30,27 @@ public void DecryptToken(TokenDecryptingTheoryData theoryData) theoryData.Token = new JsonWebToken(tokenString); } - if (theoryData.TestId == "Invalid_NoKeysProvided") - { -#pragma warning disable CS0219 // Variable is assigned but its value is never used - var something = 0; -#pragma warning restore CS0219 // Variable is assigned but its value is never used - } - CompareContext context = TestUtilities.WriteHeader($"{this}.JsonWebTokenHandlerDecryptTokenTests", theoryData); - TokenDecryptionResult tokenDecryptionResult = jsonWebTokenHandler.DecryptToken( + Result result = jsonWebTokenHandler.DecryptToken( theoryData.Token, theoryData.ValidationParameters, theoryData.Configuration, new CallContext()); - if (tokenDecryptionResult.Exception != null) - theoryData.ExpectedException.ProcessException(tokenDecryptionResult.Exception); - else - theoryData.ExpectedException.ProcessNoException(); + if (result.IsSuccess) + { + IdentityComparer.AreStringsEqual( + result.UnwrapResult(), + theoryData.Result.UnwrapResult(), + context); - IdentityComparer.AreTokenDecryptingResultsEqual( - tokenDecryptionResult, - theoryData.TokenDecryptionResult, - context); + theoryData.ExpectedException.ProcessNoException(context); + } + else + { + Exception exception = result.UnwrapError().GetException(); + theoryData.ExpectedException.ProcessException(exception, context); + } TestUtilities.AssertFailIfErrors(context); } @@ -61,13 +59,13 @@ public void DecryptToken(TokenDecryptingTheoryData theoryData) public void DecryptToken_ThrowsIfAccessingSecurityTokenOnFailedRead() { JsonWebTokenHandler jsonWebTokenHandler = new JsonWebTokenHandler(); - TokenDecryptionResult tokenDecryptionResult = jsonWebTokenHandler.DecryptToken( + Result tokenDecryptionResult = jsonWebTokenHandler.DecryptToken( null, null, null, new CallContext()); - Assert.Throws(() => tokenDecryptionResult.DecryptedToken()); + Assert.Throws(() => tokenDecryptionResult.UnwrapResult()); } public static TheoryData JsonWebTokenHandlerDecryptTokenTestCases @@ -104,13 +102,11 @@ public static TheoryData JsonWebTokenHandlerDecryptTo Token = token, ValidationParameters = new ValidationParameters(), ExpectedException = ExpectedException.SecurityTokenException("IDX10612:"), - TokenDecryptionResult = new TokenDecryptionResult( - token, - ValidationFailureType.TokenDecryptionFailed, - new ExceptionDetail( - new MessageDetail(TokenLogMessages.IDX10612), - ExceptionDetail.ExceptionType.SecurityToken, - null)), + Result = new ExceptionDetail( + new MessageDetail(TokenLogMessages.IDX10612), + ValidationErrorType.SecurityToken, + null, + null), }, new TokenDecryptingTheoryData { @@ -118,12 +114,11 @@ public static TheoryData JsonWebTokenHandlerDecryptTo Token = null, ValidationParameters = new ValidationParameters(), ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), - TokenDecryptionResult = new TokenDecryptionResult( - null, - ValidationFailureType.TokenDecryptionFailed, - new ExceptionDetail( + Result = new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10000, "jwtToken"), - ExceptionDetail.ExceptionType.ArgumentNull)), + ValidationErrorType.ArgumentNull, + null, + null), }, new TokenDecryptingTheoryData { @@ -131,12 +126,11 @@ public static TheoryData JsonWebTokenHandlerDecryptTo Token = token, ValidationParameters = null, ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), - TokenDecryptionResult = new TokenDecryptionResult( - token, - ValidationFailureType.TokenDecryptionFailed, - new ExceptionDetail( - new MessageDetail(TokenLogMessages.IDX10000, "validationParameters"), - ExceptionDetail.ExceptionType.ArgumentNull)), + Result = new ExceptionDetail( + new MessageDetail(TokenLogMessages.IDX10000, "validationParameters"), + ValidationErrorType.ArgumentNull, + null, + null), }, new TokenDecryptingTheoryData { @@ -146,9 +140,7 @@ public static TheoryData JsonWebTokenHandlerDecryptTo { TokenDecryptionKeys = [Default.SymmetricEncryptingCredentials.Key], }, - TokenDecryptionResult = new TokenDecryptionResult( - "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJlbWFpbCI6IkJvYkBjb250b3NvLmNvbSIsImdpdmVuX25hbWUiOiJCb2IiLCJpc3MiOiJodHRwOi8vRGVmYXVsdC5Jc3N1ZXIuY29tIiwiYXVkIjoiaHR0cDovL0RlZmF1bHQuQXVkaWVuY2UuY29tIiwiaWF0IjoiMTQ4OTc3NTYxNyIsIm5iZiI6IjE0ODk3NzU2MTciLCJleHAiOiIyNTM0MDIzMDA3OTkifQ.", - new JsonWebToken(ReferenceTokens.JWEDirectEncryptionUnsignedInnerJWTWithAdditionalHeaderClaims)), + Result = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJlbWFpbCI6IkJvYkBjb250b3NvLmNvbSIsImdpdmVuX25hbWUiOiJCb2IiLCJpc3MiOiJodHRwOi8vRGVmYXVsdC5Jc3N1ZXIuY29tIiwiYXVkIjoiaHR0cDovL0RlZmF1bHQuQXVkaWVuY2UuY29tIiwiaWF0IjoiMTQ4OTc3NTYxNyIsIm5iZiI6IjE0ODk3NzU2MTciLCJleHAiOiIyNTM0MDIzMDA3OTkifQ.", }, new TokenDecryptingTheoryData { @@ -158,9 +150,7 @@ public static TheoryData JsonWebTokenHandlerDecryptTo { TokenDecryptionKeyResolver = (tokenString, token, kid, validationParameters, callContext) => [Default.SymmetricEncryptingCredentials.Key] }, - TokenDecryptionResult = new TokenDecryptionResult( - "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJlbWFpbCI6IkJvYkBjb250b3NvLmNvbSIsImdpdmVuX25hbWUiOiJCb2IiLCJpc3MiOiJodHRwOi8vRGVmYXVsdC5Jc3N1ZXIuY29tIiwiYXVkIjoiaHR0cDovL0RlZmF1bHQuQXVkaWVuY2UuY29tIiwiaWF0IjoiMTQ4OTc3NTYxNyIsIm5iZiI6IjE0ODk3NzU2MTciLCJleHAiOiIyNTM0MDIzMDA3OTkifQ.", - new JsonWebToken(ReferenceTokens.JWEDirectEncryptionUnsignedInnerJWTWithAdditionalHeaderClaims)), + Result = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJlbWFpbCI6IkJvYkBjb250b3NvLmNvbSIsImdpdmVuX25hbWUiOiJCb2IiLCJpc3MiOiJodHRwOi8vRGVmYXVsdC5Jc3N1ZXIuY29tIiwiYXVkIjoiaHR0cDovL0RlZmF1bHQuQXVkaWVuY2UuY29tIiwiaWF0IjoiMTQ4OTc3NTYxNyIsIm5iZiI6IjE0ODk3NzU2MTciLCJleHAiOiIyNTM0MDIzMDA3OTkifQ.", }, new TokenDecryptingTheoryData { @@ -168,9 +158,7 @@ public static TheoryData JsonWebTokenHandlerDecryptTo TokenString = ReferenceTokens.JWEDirectEncryptionUnsignedInnerJWTWithAdditionalHeaderClaims, ValidationParameters = new ValidationParameters(), Configuration = new CustomConfiguration(Default.SymmetricEncryptingCredentials.Key), - TokenDecryptionResult = new TokenDecryptionResult( - "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJlbWFpbCI6IkJvYkBjb250b3NvLmNvbSIsImdpdmVuX25hbWUiOiJCb2IiLCJpc3MiOiJodHRwOi8vRGVmYXVsdC5Jc3N1ZXIuY29tIiwiYXVkIjoiaHR0cDovL0RlZmF1bHQuQXVkaWVuY2UuY29tIiwiaWF0IjoiMTQ4OTc3NTYxNyIsIm5iZiI6IjE0ODk3NzU2MTciLCJleHAiOiIyNTM0MDIzMDA3OTkifQ.", - new JsonWebToken(ReferenceTokens.JWEDirectEncryptionUnsignedInnerJWTWithAdditionalHeaderClaims)), + Result = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJlbWFpbCI6IkJvYkBjb250b3NvLmNvbSIsImdpdmVuX25hbWUiOiJCb2IiLCJpc3MiOiJodHRwOi8vRGVmYXVsdC5Jc3N1ZXIuY29tIiwiYXVkIjoiaHR0cDovL0RlZmF1bHQuQXVkaWVuY2UuY29tIiwiaWF0IjoiMTQ4OTc3NTYxNyIsIm5iZiI6IjE0ODk3NzU2MTciLCJleHAiOiIyNTM0MDIzMDA3OTkifQ.", }, #if NET472 || NET6_0_OR_GREATER new TokenDecryptingTheoryData @@ -182,9 +170,7 @@ public static TheoryData JsonWebTokenHandlerDecryptTo TokenDecryptionKeys = [new ECDsaSecurityKey(KeyingMaterial.JsonWebKeyP256, true)], EphemeralDecryptionKey = new ECDsaSecurityKey(KeyingMaterial.JsonWebKeyP256, true) }, - TokenDecryptionResult = new TokenDecryptionResult( - "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJleHAiOjI1MzQwMjMwMDgwMCwiaWF0IjowLCJuYmYiOjB9.", - ecdsaToken), + Result = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJleHAiOjI1MzQwMjMwMDgwMCwiaWF0IjowLCJuYmYiOjB9." }, #endif new TokenDecryptingTheoryData @@ -193,17 +179,15 @@ public static TheoryData JsonWebTokenHandlerDecryptTo TokenString = ReferenceTokens.JWEDirectEncryptionUnsignedInnerJWTWithAdditionalHeaderClaims, ValidationParameters = new ValidationParameters(), ExpectedException = ExpectedException.SecurityTokenDecryptionFailedException("IDX10609:"), - TokenDecryptionResult = new TokenDecryptionResult( - new JsonWebToken(ReferenceTokens.JWEDirectEncryptionUnsignedInnerJWTWithAdditionalHeaderClaims), - ValidationFailureType.TokenDecryptionFailed, - new ExceptionDetail( - new MessageDetail( - TokenLogMessages.IDX10609, - LogHelper.MarkAsSecurityArtifact( - new JsonWebToken(ReferenceTokens.JWEDirectEncryptionUnsignedInnerJWTWithAdditionalHeaderClaims), - JwtTokenUtilities.SafeLogJwtToken)), - ExceptionDetail.ExceptionType.SecurityTokenDecryptionFailed, - null)), + Result = new ExceptionDetail( + new MessageDetail( + TokenLogMessages.IDX10609, + LogHelper.MarkAsSecurityArtifact( + new JsonWebToken(ReferenceTokens.JWEDirectEncryptionUnsignedInnerJWTWithAdditionalHeaderClaims), + JwtTokenUtilities.SafeLogJwtToken)), + ValidationErrorType.SecurityTokenDecryptionFailed, + null, + null), } }; } @@ -213,7 +197,7 @@ public static TheoryData JsonWebTokenHandlerDecryptTo public class TokenDecryptingTheoryData : TheoryDataBase { public JsonWebToken Token { get; set; } - internal TokenDecryptionResult TokenDecryptionResult { get; set; } + internal Result Result { get; set; } public BaseConfiguration Configuration { get; internal set; } public SecurityTokenDescriptor SecurityTokenDescriptor { get; internal set; } public string TokenString { get; internal set; } diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs index 3e16ff62dd..477985885b 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs @@ -3,6 +3,7 @@ using System; using System.IdentityModel.Tokens.Jwt.Tests; +using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.TestUtils; using Microsoft.IdentityModel.Tokens; @@ -17,19 +18,23 @@ public class JsonWebTokenHandlerReadTokenTests public void ReadToken(TokenReadingTheoryData theoryData) { CompareContext context = TestUtilities.WriteHeader($"{this}.JsonWebTokenHandlerReadTokenTests", theoryData); - TokenReadingResult tokenReadingResult = JsonWebTokenHandler.ReadToken( + Result result = JsonWebTokenHandler.ReadToken( theoryData.Token, new CallContext()); - if (tokenReadingResult.Exception != null) - theoryData.ExpectedException.ProcessException(tokenReadingResult.Exception); - else - theoryData.ExpectedException.ProcessNoException(); + if (result.IsSuccess) + { + IdentityComparer.AreEqual(result.UnwrapResult(), + theoryData.Result.UnwrapResult(), + context); - IdentityComparer.AreTokenReadingResultsEqual( - tokenReadingResult, - theoryData.TokenReadingResult, - context); + theoryData.ExpectedException.ProcessNoException(context); + } + else + { + Exception exception = result.UnwrapError().GetException(); + theoryData.ExpectedException.ProcessException(exception, context); + } TestUtilities.AssertFailIfErrors(context); } @@ -37,11 +42,11 @@ public void ReadToken(TokenReadingTheoryData theoryData) [Fact] public void ReadToken_ThrowsIfAccessingSecurityTokenOnFailedRead() { - TokenReadingResult tokenReadingResult = JsonWebTokenHandler.ReadToken( + Result result = JsonWebTokenHandler.ReadToken( null, new CallContext()); - Assert.Throws(() => tokenReadingResult.SecurityToken()); + Assert.Throws(() => result.UnwrapResult()); } public static TheoryData JsonWebTokenHandlerReadTokenTestCases @@ -55,37 +60,33 @@ public static TheoryData JsonWebTokenHandlerReadTokenTes { TestId = "Valid_Jwt", Token = validToken, - TokenReadingResult = new TokenReadingResult( - new JsonWebToken(validToken), - validToken) + Result = new JsonWebToken(validToken), }, new TokenReadingTheoryData { TestId = "Invalid_NullToken", Token = null, ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), - TokenReadingResult = new TokenReadingResult( + Result = new ExceptionDetail( + new MessageDetail( + TokenLogMessages.IDX10000, + LogHelper.MarkAsNonPII("token")), + ValidationErrorType.ArgumentNull, null, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - TokenLogMessages.IDX10000, - LogHelper.MarkAsNonPII("token")), - ExceptionDetail.ExceptionType.ArgumentNull)) + null) }, new TokenReadingTheoryData { TestId = "Invalid_EmptyToken", Token = string.Empty, ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), - TokenReadingResult = new TokenReadingResult( - string.Empty, - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - TokenLogMessages.IDX10000, - LogHelper.MarkAsNonPII("token")), - ExceptionDetail.ExceptionType.ArgumentNull)) + Result = new ExceptionDetail( + new MessageDetail( + TokenLogMessages.IDX10000, + LogHelper.MarkAsNonPII("token")), + ValidationErrorType.ArgumentNull, + null, + null) }, new TokenReadingTheoryData { @@ -94,14 +95,13 @@ public static TheoryData JsonWebTokenHandlerReadTokenTes ExpectedException = ExpectedException.SecurityTokenMalformedTokenException( "IDX14107:", typeof(SecurityTokenMalformedException)), - TokenReadingResult = new TokenReadingResult( - "malformed-token", - ValidationFailureType.TokenReadingFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX14107, - LogHelper.MarkAsNonPII("token")), - ExceptionDetail.ExceptionType.SecurityTokenMalformed)) + Result = new ExceptionDetail( + new MessageDetail( + LogMessages.IDX14107, + LogHelper.MarkAsNonPII("token")), + ValidationErrorType.SecurityTokenMalformed, + null, + new SecurityTokenMalformedException()), } }; } @@ -111,6 +111,6 @@ public static TheoryData JsonWebTokenHandlerReadTokenTes public class TokenReadingTheoryData : TheoryDataBase { public string Token { get; set; } - public object TokenReadingResult { get; set; } + internal Result Result { get; set; } } } diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs index d6a8287810..bf803e9a25 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs @@ -3,7 +3,7 @@ using System; using System.IdentityModel.Tokens.Jwt.Tests; -using Microsoft.IdentityModel.JsonWebTokens.Results; +using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.TestUtils; @@ -39,21 +39,30 @@ public void ValidateSignature(JsonWebTokenHandlerValidateSignatureTheoryData the if (theoryData.ValidationParameters is not null && theoryData.KeyToAddToValidationParameters is not null) theoryData.ValidationParameters.IssuerSigningKeys.Add(theoryData.KeyToAddToValidationParameters); - SignatureValidationResult validationResult = JsonWebTokenHandler.ValidateSignature( - jsonWebToken, - theoryData.ValidationParameters, - theoryData.Configuration, - new CallContext + Result result = JsonWebTokenHandler.ValidateSignature( + jsonWebToken, + theoryData.ValidationParameters, + theoryData.Configuration, + new CallContext + { + DebugId = theoryData.TestId + }); + + if (result.IsSuccess) { - DebugId = theoryData.TestId - }); + IdentityComparer.AreSecurityKeysEqual( + result.UnwrapResult(), + theoryData.Result.UnwrapResult(), + context); - if (validationResult.Exception != null) - theoryData.ExpectedException.ProcessException(validationResult.Exception); + theoryData.ExpectedException.ProcessNoException(context); + } else - theoryData.ExpectedException?.ProcessNoException(); + { + Exception exception = result.UnwrapError().GetException(); + theoryData.ExpectedException.ProcessException(exception, context); + } - IdentityComparer.AreSignatureValidationResultsEqual(validationResult, theoryData.SignatureValidationResult, context); TestUtilities.AssertFailIfErrors(context); } @@ -68,42 +77,42 @@ public static TheoryData JsonWeb TestId = "Invalid_Null_JWT", JWT = null, ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), - SignatureValidationResult = new SignatureValidationResult( - ValidationFailureType.SignatureValidationFailed, - new ExceptionDetail( - new MessageDetail( - TokenLogMessages.IDX10000, - "jwtToken"), - ExceptionDetail.ExceptionType.ArgumentNull)) + Result = new ExceptionDetail( + new MessageDetail( + TokenLogMessages.IDX10000, + "jwtToken"), + ValidationErrorType.ArgumentNull, + null, + null) }, new JsonWebTokenHandlerValidateSignatureTheoryData { TestId = "Invalid_Null_ValidationParameters", JWT = new JsonWebToken(EncodedJwts.LiveJwt), ValidationParameters = null, ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), - SignatureValidationResult = new SignatureValidationResult( - ValidationFailureType.SignatureValidationFailed, - new ExceptionDetail( - new MessageDetail( - TokenLogMessages.IDX10000, - "validationParameters"), - ExceptionDetail.ExceptionType.ArgumentNull)) + Result = new ExceptionDetail( + new MessageDetail( + TokenLogMessages.IDX10000, + "validationParameters"), + ValidationErrorType.ArgumentNull, + null, + null) }, new JsonWebTokenHandlerValidateSignatureTheoryData { TestId = "Invalid_DelegateReturnsFailure", JWT = new JsonWebToken(EncodedJwts.LiveJwt), ValidationParameters = new ValidationParameters { - SignatureValidator = (token, parameters, configuration, callContext) => SignatureValidationResult.NullParameterFailure("fakeParameter") + SignatureValidator = (token, parameters, configuration, callContext) => ExceptionDetail.NullParameter("fakeParameter", null) }, ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), - SignatureValidationResult = new SignatureValidationResult( - ValidationFailureType.SignatureValidationFailed, - new ExceptionDetail( - new MessageDetail( - TokenLogMessages.IDX10000, - "fakeParameter"), - ExceptionDetail.ExceptionType.ArgumentNull)) + Result = new ExceptionDetail( + new MessageDetail( + TokenLogMessages.IDX10000, + "fakeParameter"), + ValidationErrorType.ArgumentNull, + null, + null) }, new JsonWebTokenHandlerValidateSignatureTheoryData { @@ -111,13 +120,13 @@ public static TheoryData JsonWeb JWT = unsignedToken, ValidationParameters = new ValidationParameters(), ExpectedException = ExpectedException.SecurityTokenInvalidSignatureException("IDX10504:"), - SignatureValidationResult = new SignatureValidationResult( - ValidationFailureType.SignatureValidationFailed, - new ExceptionDetail( - new MessageDetail( - TokenLogMessages.IDX10504, - LogHelper.MarkAsSecurityArtifact(unsignedToken, JwtTokenUtilities.SafeLogJwtToken)), - ExceptionDetail.ExceptionType.SecurityTokenInvalidSignature)) + Result = new ExceptionDetail( + new MessageDetail( + TokenLogMessages.IDX10504, + LogHelper.MarkAsSecurityArtifact(unsignedToken, JwtTokenUtilities.SafeLogJwtToken)), + ValidationErrorType.SecurityTokenInvalidSignature, + null, + null) }, new JsonWebTokenHandlerValidateSignatureTheoryData { @@ -125,9 +134,9 @@ public static TheoryData JsonWeb JWT = new JsonWebToken(EncodedJwts.LiveJwt), ValidationParameters = new ValidationParameters { - SignatureValidator = (token, parameters, configuration, callContext) => SignatureValidationResult.Success() + SignatureValidator = (token, parameters, configuration, callContext) => KeyingMaterial.JsonWebKeyRsa256PublicSigningCredentials.Key }, - SignatureValidationResult = SignatureValidationResult.Success() + Result = KeyingMaterial.JsonWebKeyRsa256PublicSigningCredentials.Key }, new JsonWebTokenHandlerValidateSignatureTheoryData { @@ -135,7 +144,7 @@ public static TheoryData JsonWeb SigningCredentials = KeyingMaterial.JsonWebKeyRsa256SigningCredentials, ValidationParameters = new ValidationParameters(), KeyToAddToValidationParameters = KeyingMaterial.JsonWebKeyRsa256SigningCredentials.Key, - SignatureValidationResult = SignatureValidationResult.Success(), + Result = KeyingMaterial.JsonWebKeyRsa256SigningCredentials.Key, }, new JsonWebTokenHandlerValidateSignatureTheoryData { @@ -143,7 +152,7 @@ public static TheoryData JsonWeb SigningCredentials = KeyingMaterial.X509SigningCreds_1024_RsaSha2_Sha2, ValidationParameters = new ValidationParameters(), KeyToAddToValidationParameters = KeyingMaterial.X509SigningCreds_1024_RsaSha2_Sha2.Key, - SignatureValidationResult = SignatureValidationResult.Success() + Result = KeyingMaterial.X509SigningCreds_1024_RsaSha2_Sha2.Key, }, new JsonWebTokenHandlerValidateSignatureTheoryData { @@ -153,7 +162,7 @@ public static TheoryData JsonWeb { IssuerSigningKeyResolver = (token, securityToken, kid, validationParameters, configuration, callContext) => KeyingMaterial.JsonWebKeyRsa256SigningCredentials.Key }, - SignatureValidationResult = SignatureValidationResult.Success() + Result = KeyingMaterial.JsonWebKeyRsa256SigningCredentials.Key }, new JsonWebTokenHandlerValidateSignatureTheoryData { @@ -162,7 +171,7 @@ public static TheoryData JsonWeb Configuration = new OpenIdConnectConfiguration(), KeyToAddToConfiguration = KeyingMaterial.JsonWebKeyRsa256SigningCredentials.Key, ValidationParameters = new ValidationParameters(), - SignatureValidationResult = SignatureValidationResult.Success() + Result = KeyingMaterial.JsonWebKeyRsa256SigningCredentials.Key, }, new JsonWebTokenHandlerValidateSignatureTheoryData { @@ -173,7 +182,7 @@ public static TheoryData JsonWeb TryAllIssuerSigningKeys = true }, KeyToAddToValidationParameters = KeyingMaterial.DefaultSymmetricSigningCreds_256_Sha2_NoKeyId.Key, - SignatureValidationResult = SignatureValidationResult.Success() + Result = KeyingMaterial.DefaultSymmetricSigningCreds_256_Sha2_NoKeyId.Key, }, new JsonWebTokenHandlerValidateSignatureTheoryData { @@ -182,11 +191,11 @@ public static TheoryData JsonWeb ValidationParameters = new ValidationParameters(), KeyToAddToValidationParameters = KeyingMaterial.DefaultSymmetricSigningCreds_256_Sha2_NoKeyId.Key, ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException("IDX10500:"), - SignatureValidationResult = new SignatureValidationResult( - ValidationFailureType.SignatureValidationFailed, - new ExceptionDetail( - new MessageDetail(TokenLogMessages.IDX10500), - ExceptionDetail.ExceptionType.SecurityTokenSignatureKeyNotFound)) + Result = new ExceptionDetail( + new MessageDetail(TokenLogMessages.IDX10500), + ValidationErrorType.SecurityTokenSignatureKeyNotFound, + null, + null) }, new JsonWebTokenHandlerValidateSignatureTheoryData { @@ -194,11 +203,11 @@ public static TheoryData JsonWeb JWT = new JsonWebToken(EncodedJwts.LiveJwt), ValidationParameters = new ValidationParameters(), ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException("IDX10500:"), - SignatureValidationResult = new SignatureValidationResult( - ValidationFailureType.SignatureValidationFailed, - new ExceptionDetail( - new MessageDetail(TokenLogMessages.IDX10500), - ExceptionDetail.ExceptionType.SecurityTokenSignatureKeyNotFound)) + Result = new ExceptionDetail( + new MessageDetail(TokenLogMessages.IDX10500), + ValidationErrorType.SecurityTokenSignatureKeyNotFound, + null, + null) } }; } @@ -212,7 +221,7 @@ public class JsonWebTokenHandlerValidateSignatureTheoryData : TheoryDataBase public SigningCredentials SigningCredentials { get; internal set; } public SecurityKey KeyToAddToConfiguration { get; internal set; } public SecurityKey KeyToAddToValidationParameters { get; internal set; } - internal SignatureValidationResult SignatureValidationResult { get; set; } + internal Result Result { get; set; } internal ValidationParameters ValidationParameters { get; set; } } } diff --git a/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs b/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs index 306106b47e..c03a0b0afd 100644 --- a/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs +++ b/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs @@ -20,6 +20,7 @@ using System.Security.Cryptography.X509Certificates; using System.Text.Json; using System.Text.RegularExpressions; +using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Protocols.OpenIdConnect; @@ -1293,6 +1294,27 @@ internal static bool AreValidatedSigningKeyLifetimesEqual(ValidatedSigningKeyLif return context.Merge(localContext); } + internal static bool AreValidatedTokenTypesEqual(ValidatedTokenType validatedTokenType1, ValidatedTokenType validatedTokenType2, CompareContext context) + { + var localContext = new CompareContext(context); + + AreStringsEqual( + validatedTokenType1.Type, + validatedTokenType2.Type, + "validatedTokenType1.Type", + "validatedTokenType2.Type", + localContext); + + AreIntsEqual( + validatedTokenType1.ValidTypeCount, + validatedTokenType2.ValidTypeCount, + "validatedTokenType1.ValidTypeCount", + "validatedTokenType2.ValidTypeCount", + localContext); + + return context.Merge(localContext); + } + internal static bool AreTokenValidationErrorsEqual(TokenValidationError tokenValidationError1, TokenValidationError tokenValidationError2, CompareContext context) { var localContext = new CompareContext(context); diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs index 709da8b0a4..ca931e3b3f 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs @@ -35,7 +35,7 @@ public void ValidateAlgorithm(AlgorithmTheoryData theoryData) else { Exception exception = result.UnwrapError().GetException(); - theoryData.ExpectedException.ProcessException(exception); + theoryData.ExpectedException.ProcessException(exception, context); } TestUtilities.AssertFailIfErrors(context); diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AsyncValidatorsTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AsyncValidatorsTests.cs deleted file mode 100644 index d96f7bc596..0000000000 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AsyncValidatorsTests.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.IdentityModel.TestUtils; -using Xunit; - -namespace Microsoft.IdentityModel.Tokens.Validation.Tests -{ - public class AsyncValidatorTests - { - [Theory, MemberData(nameof(AsyncIssuerValidatorTestCases))] - public async Task AsyncIssuerValidatorTests(IssuerValidatorTheoryData theoryData) - { - CompareContext context = TestUtilities.WriteHeader($"{this}.AsyncIssuerValidatorTests", theoryData); - try - { - IssuerValidationResult result = await Validators.ValidateIssuerAsync( - theoryData.Issuer, - theoryData.SecurityToken, - theoryData.ValidationParameters, - null, - CancellationToken.None).ConfigureAwait(false); - Exception exception = result.Exception; - context.Diffs.Add("Exception: " + exception.ToString()); - } - catch (Exception ex) - { - context.Diffs.Add("Exception: " + ex.ToString()); - } - } - - public static TheoryData AsyncIssuerValidatorTestCases - { - get - { - TheoryData theoryData = new TheoryData(); - - theoryData.Add(new IssuerValidatorTheoryData - { - Issuer = null, - ValidationParameters = new ValidationParameters(), - }); - - return theoryData; - } - } - } - - public class IssuerValidatorTheoryData : TheoryDataBase - { - public string Issuer { get; set; } - internal ValidationParameters ValidationParameters { get; set; } - public SecurityToken SecurityToken { get; set; } - } -} diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs index 523ba85d99..c3026d8182 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs @@ -25,28 +25,25 @@ public void ValidateAudienceParameters(AudienceValidationTheoryData theoryData) theoryData.ValidationParameters.ValidAudiences.Add(audience); } - Result result = Validators.ValidateAudience( + Result result = Validators.ValidateAudience( theoryData.Audiences, theoryData.SecurityToken, theoryData.ValidationParameters, new CallContext()); if (result.IsSuccess) + { IdentityComparer.AreStringsEqual( result.UnwrapResult(), theoryData.Result.UnwrapResult(), context); + + theoryData.ExpectedException.ProcessNoException(context); + } else { - IdentityComparer.AreTokenValidationErrorsEqual( - result.UnwrapError(), - theoryData.Result.UnwrapError(), - context); - - if (result.UnwrapError().InnerException is not null) - theoryData.ExpectedException.ProcessException(result.UnwrapError().InnerException); - else - theoryData.ExpectedException.ProcessNoException(); + Exception exception = result.UnwrapError().GetException(); + theoryData.ExpectedException.ProcessException(exception, context); } TestUtilities.AssertFailIfErrors(context); @@ -76,64 +73,72 @@ public static TheoryData ValidateAudienceTestCases new AudienceValidationTheoryData { Audiences = new List { "audience1" }, + ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), TestId = "Invalid_ValidationParametersIsNull", ValidationParameters = null, - Result = new TokenValidationError( - ValidationErrorType.ArgumentNull, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), + ValidationErrorType.ArgumentNull, + null, null) }, new AudienceValidationTheoryData { Audiences = null, TestId = "Invalid_AudiencesIsNull", - Result = new TokenValidationError( + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10207:"), + Result = new ExceptionDetail( + new MessageDetail(LogMessages.IDX10207), ValidationErrorType.SecurityTokenInvalidAudience, - new MessageDetail( - LogMessages.IDX10207, - null), + null, null) }, new AudienceValidationTheoryData { Audiences = new List{ }, TestId = "Invalid_AudiencesIsEmptyList", + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10206:"), ValidationParameters = new ValidationParameters(), - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10206, null), + ValidationErrorType.SecurityTokenInvalidAudience, + null, null) }, new AudienceValidationTheoryData { Audiences = new List { "audience1" }, TestId = "Invalid_ValidAudiencesIsEmptyString", + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), ValidationParameters = new ValidationParameters(), AudiencesToAdd = [String.Empty], - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10215, LogHelper.MarkAsNonPII("audience1"), LogHelper.MarkAsNonPII(String.Empty)), + ValidationErrorType.SecurityTokenInvalidAudience, + null, null) }, new AudienceValidationTheoryData { Audiences = new List { "audience1" }, TestId = "Invalid_ValidAudiencesIsWhiteSpace", + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), ValidationParameters = new ValidationParameters(), AudiencesToAdd = [" "], - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10215, LogHelper.MarkAsNonPII("audience1"), LogHelper.MarkAsNonPII(" ")), + ValidationErrorType.SecurityTokenInvalidAudience, + null, null) }, new AudienceValidationTheoryData @@ -149,58 +154,65 @@ public static TheoryData ValidateAudienceTestCases { Audiences = audiences1, TestId = "Invalid_SameLengthNotMatched", + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience2], SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, "Issuer"), - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience2)), + ValidationErrorType.SecurityTokenInvalidAudience, + null, null) }, new AudienceValidationTheoryData { Audiences = audiences1, TestId = "Invalid_AudiencesValidAudienceWithSlashNotMatched", + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience2 + "/"], SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, "Issuer"), - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience2Slash)), + ValidationErrorType.SecurityTokenInvalidAudience, + null, null) }, new AudienceValidationTheoryData { Audiences = audiences2WithSlash, TestId = "Invalid_AudiencesWithSlashValidAudienceSameLengthNotMatched", + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience1], - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience2Slash), LogHelper.MarkAsNonPII(audience1)), + ValidationErrorType.SecurityTokenInvalidAudience, + null, null) }, new AudienceValidationTheoryData { Audiences = audiences1, TestId = "Invalid_ValidAudienceWithSlash_IgnoreTrailingSlashFalse", + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), ValidationParameters = new ValidationParameters{ IgnoreTrailingSlashWhenValidatingAudience = false }, AudiencesToAdd = [audience1 + "/"], - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience1Slash)), + ValidationErrorType.SecurityTokenInvalidAudience, null) }, new AudienceValidationTheoryData @@ -215,14 +227,16 @@ public static TheoryData ValidateAudienceTestCases { Audiences = audiences1, TestId = "Invalid_ValidAudiencesWithSlash_IgnoreTrailingSlashFalse", + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), ValidationParameters = new ValidationParameters{ IgnoreTrailingSlashWhenValidatingAudience = false }, AudiencesToAdd = audiences1WithSlash, - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(commaAudience1Slash)), + ValidationErrorType.SecurityTokenInvalidAudience, + null, null) }, new AudienceValidationTheoryData @@ -237,56 +251,64 @@ public static TheoryData ValidateAudienceTestCases { Audiences = audiences1, TestId = "Invalid_ValidAudienceWithExtraChar", + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience1 + "A"], - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience1 + "A")), + ValidationErrorType.SecurityTokenInvalidAudience, + null, null) }, new AudienceValidationTheoryData { Audiences = audiences1, TestId = "Invalid_ValidAudienceWithDoubleSlash_IgnoreTrailingSlashTrue", + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience1 + "//"], - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience1 + "//")), + ValidationErrorType.SecurityTokenInvalidAudience, + null, null) }, new AudienceValidationTheoryData { Audiences = audiences1, TestId = "Invalid_ValidAudiencesWithDoubleSlash_IgnoreTrailingSlashTrue", + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), ValidationParameters = new ValidationParameters(), AudiencesToAdd = audiences1WithTwoSlashes, - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(commaAudience1 + "//")), + ValidationErrorType.SecurityTokenInvalidAudience, + null, null) }, new AudienceValidationTheoryData { Audiences = audiences1WithSlash, TestId = "Invalid_TokenAudienceWithSlash_IgnoreTrailingSlashFalse", + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), ValidationParameters = new ValidationParameters{ IgnoreTrailingSlashWhenValidatingAudience = false }, AudiencesToAdd = [audience1], - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1Slash), LogHelper.MarkAsNonPII(audience1)), + ValidationErrorType.SecurityTokenInvalidAudience, + null, null) }, new AudienceValidationTheoryData @@ -301,28 +323,32 @@ public static TheoryData ValidateAudienceTestCases { Audiences = audiences2WithSlash, TestId = "Invalid_TokenAudienceWithSlashNotEqual", + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience1], - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience2Slash), LogHelper.MarkAsNonPII(audience1)), + ValidationErrorType.SecurityTokenInvalidAudience, + null, null) }, new AudienceValidationTheoryData { Audiences = audiences1WithSlash, TestId = "Invalid_TokenAudiencesWithSlash_IgnoreTrailingSlashFalse", + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), ValidationParameters = new ValidationParameters{ IgnoreTrailingSlashWhenValidatingAudience = false }, AudiencesToAdd = [audience1], - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1Slash), LogHelper.MarkAsNonPII(audience1)), + ValidationErrorType.SecurityTokenInvalidAudience, + null, null) }, new AudienceValidationTheoryData @@ -337,28 +363,32 @@ public static TheoryData ValidateAudienceTestCases { Audiences = audiences1WithSlash, TestId = "Invalid_TokenAudiencesWithSlashValidAudiencesNotMatched_IgnoreTrailingSlashTrue", + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), ValidationParameters = new ValidationParameters(), AudiencesToAdd = audiences2, - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1Slash), LogHelper.MarkAsNonPII(commaAudience2)), + ValidationErrorType.SecurityTokenInvalidAudience, + null, null) }, new AudienceValidationTheoryData { Audiences = audiences1WithTwoSlashes, TestId = "TokenAudienceWithTwoSlashesVPTrue", + ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10215:"), ValidationParameters = new ValidationParameters(), AudiencesToAdd = [audience1], - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidAudience, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1 + "//"), LogHelper.MarkAsNonPII(audience1)), + ValidationErrorType.SecurityTokenInvalidAudience, + null, null) } }; @@ -377,7 +407,7 @@ public class AudienceValidationTheoryData : TheoryDataBase public List AudiencesToAdd { get; internal set; } - internal Result Result { get; set; } + internal Result Result { get; set; } } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ExceptionDetailsTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ExceptionDetailsTests.cs index a0fa29f323..ac77b5b632 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ExceptionDetailsTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ExceptionDetailsTests.cs @@ -17,7 +17,8 @@ public void ExceptionDetails(ExceptionDetailsTheoryData theoryData) var context = TestUtilities.WriteHeader($"{this}.ExceptionDetails", theoryData); ExceptionDetail exceptionDetail = new ExceptionDetail( new MessageDetail(""), - theoryData.ExceptionType); + theoryData.ExceptionType, + null); theoryData.ExpectedException.ProcessException(exceptionDetail.GetException(), context); @@ -29,7 +30,8 @@ public void ExceptionDetails_UnknownType_Throws() { ExceptionDetail exceptionDetail = new ExceptionDetail( new MessageDetail(""), - ExceptionDetail.ExceptionType.Unknown); + ValidationErrorType.Unknown, + null); Assert.Throws(() => exceptionDetail.GetException()); } @@ -37,8 +39,8 @@ public void ExceptionDetails_UnknownType_Throws() [Fact] public void All_ExceptionDetails_HaveTests() { - // If this test fails, we are missing a test for a new ExceptionDetail.ExceptionType - Assert.Equal(((int)ExceptionDetail.ExceptionType.ExceptionTypeCount), ExceptionDetailsTestCases.Count()); + // If this test fails, we are missing a test for a new ValidationErrorType + Assert.Equal(((int)ValidationErrorType.ExceptionTypeCount), ExceptionDetailsTestCases.Count()); } public static TheoryData ExceptionDetailsTestCases @@ -50,121 +52,127 @@ public static TheoryData ExceptionDetailsTestCases new ExceptionDetailsTheoryData { TestId = "ArgumentNull", - ExceptionType = ExceptionDetail.ExceptionType.ArgumentNull, + ExceptionType = ValidationErrorType.ArgumentNull, ExpectedException = ExpectedException.ArgumentNullException(), }, new ExceptionDetailsTheoryData + { + TestId = "InvalidArgument", + ExceptionType = ValidationErrorType.InvalidArgument, + ExpectedException = ExpectedException.ArgumentException(), + }, + new ExceptionDetailsTheoryData { TestId = "InvalidOperation", - ExceptionType = ExceptionDetail.ExceptionType.InvalidOperation, + ExceptionType = ValidationErrorType.InvalidOperation, ExpectedException = ExpectedException.InvalidOperationException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityToken", - ExceptionType = ExceptionDetail.ExceptionType.SecurityToken, + ExceptionType = ValidationErrorType.SecurityToken, ExpectedException = ExpectedException.SecurityTokenException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenDecompressionFailed", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenDecompressionFailed, + ExceptionType = ValidationErrorType.SecurityTokenDecompressionFailed, ExpectedException = ExpectedException.SecurityTokenDecompressionFailedException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenDecryptionFailed", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenDecryptionFailed, + ExceptionType = ValidationErrorType.SecurityTokenDecryptionFailed, ExpectedException = ExpectedException.SecurityTokenDecryptionFailedException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenExpired", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenExpired, + ExceptionType = ValidationErrorType.SecurityTokenExpired, ExpectedException = ExpectedException.SecurityTokenExpiredException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenInvalidAudience", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenInvalidAudience, + ExceptionType = ValidationErrorType.SecurityTokenInvalidAudience, ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenInvalidAlgorithm", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenInvalidAlgorithm, + ExceptionType = ValidationErrorType.SecurityTokenInvalidAlgorithm, ExpectedException = ExpectedException.SecurityTokenInvalidAlgorithmException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenInvalidIssuer", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenInvalidIssuer, + ExceptionType = ValidationErrorType.SecurityTokenInvalidIssuer, ExpectedException = ExpectedException.SecurityTokenInvalidIssuerException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenInvalidLifetime", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenInvalidLifetime, + ExceptionType = ValidationErrorType.SecurityTokenInvalidLifetime, ExpectedException = ExpectedException.SecurityTokenInvalidLifetimeException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenInvalidSigningKey", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenInvalidSigningKey, + ExceptionType = ValidationErrorType.SecurityTokenInvalidSigningKey, ExpectedException = ExpectedException.SecurityTokenInvalidSigningKeyException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenInvalidSignature", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenInvalidSignature, + ExceptionType = ValidationErrorType.SecurityTokenInvalidSignature, ExpectedException = ExpectedException.SecurityTokenInvalidSignatureException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenInvalidType", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenInvalidType, + ExceptionType = ValidationErrorType.SecurityTokenInvalidType, ExpectedException = ExpectedException.SecurityTokenInvalidTypeException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenKeyWrap", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenKeyWrap, + ExceptionType = ValidationErrorType.SecurityTokenKeyWrap, ExpectedException = ExpectedException.SecurityTokenKeyWrapException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenMalformed", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenMalformed, + ExceptionType = ValidationErrorType.SecurityTokenMalformed, ExpectedException = ExpectedException.SecurityTokenMalformedException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenNoExpiration", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenNoExpiration, + ExceptionType = ValidationErrorType.SecurityTokenNoExpiration, ExpectedException = ExpectedException.SecurityTokenNoExpirationException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenNotYetValid", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenNotYetValid, + ExceptionType = ValidationErrorType.SecurityTokenNotYetValid, ExpectedException = ExpectedException.SecurityTokenNotYetValidException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenReplayDetected", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenReplayDetected, + ExceptionType = ValidationErrorType.SecurityTokenReplayDetected, ExpectedException = ExpectedException.SecurityTokenReplayDetectedException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenReplayAddFailed", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenReplayAddFailed, + ExceptionType = ValidationErrorType.SecurityTokenReplayAddFailed, ExpectedException = ExpectedException.SecurityTokenReplayAddFailedException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenSignatureKeyNotFound", - ExceptionType = ExceptionDetail.ExceptionType.SecurityTokenSignatureKeyNotFound, + ExceptionType = ValidationErrorType.SecurityTokenSignatureKeyNotFound, ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException(), }, }; diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs index cd3970da62..04210ac377 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs @@ -24,7 +24,7 @@ public async Task IssuerValidatorAsyncTests(IssuerValidationResultsTheoryData th if (theoryData.ValidIssuerToAdd != null) theoryData.ValidationParameters.ValidIssuers.Add(theoryData.ValidIssuerToAdd); - Result result = await Validators.ValidateIssuerAsync( + Result result = await Validators.ValidateIssuerAsync( theoryData.Issuer, theoryData.SecurityToken, theoryData.ValidationParameters, @@ -37,18 +37,13 @@ public async Task IssuerValidatorAsyncTests(IssuerValidationResultsTheoryData th theoryData.Result.UnwrapResult(), result.UnwrapResult(), context); + + theoryData.ExpectedException.ProcessNoException(context); } else { - IdentityComparer.AreTokenValidationErrorsEqual( - result.UnwrapError(), - theoryData.Result.UnwrapError(), - context); - - if (result.UnwrapError().InnerException is not null) - theoryData.ExpectedException.ProcessException(result.UnwrapError().InnerException); - else - theoryData.ExpectedException.ProcessNoException(); + Exception exception = result.UnwrapError().GetException(); + theoryData.ExpectedException.ProcessException(exception, context); } TestUtilities.AssertFailIfErrors(context); @@ -67,14 +62,16 @@ public static TheoryData IssuerValdationResul theoryData.Add(new IssuerValidationResultsTheoryData("NULL_Issuer") { - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidIssuer, + ExpectedException = ExpectedException.SecurityTokenInvalidIssuerException("IDX10211:"), + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10211, LogHelper.MarkAsNonPII(null), LogHelper.MarkAsNonPII(validIssuer), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(null)), LogHelper.MarkAsNonPII(null)), + ValidationErrorType.SecurityTokenInvalidIssuer, + null, null), SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, issClaim), ValidationParameters = new ValidationParameters() @@ -82,12 +79,14 @@ public static TheoryData IssuerValdationResul theoryData.Add(new IssuerValidationResultsTheoryData("NULL_ValidationParameters") { + ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), Issuer = issClaim, - Result = new TokenValidationError( - ValidationErrorType.ArgumentNull, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), + ValidationErrorType.ArgumentNull, + null, null), SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, issClaim), ValidationParameters = null @@ -95,12 +94,14 @@ public static TheoryData IssuerValdationResul theoryData.Add(new IssuerValidationResultsTheoryData("NULL_SecurityToken") { + ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), Issuer = issClaim, - Result = new TokenValidationError( - ValidationErrorType.ArgumentNull, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), + ValidationErrorType.ArgumentNull, + null, null), SecurityToken = null, ValidationParameters = new ValidationParameters() @@ -128,14 +129,16 @@ public static TheoryData IssuerValdationResul theoryData.Add(new IssuerValidationResultsTheoryData("Invalid_Issuer") { + ExpectedException = ExpectedException.SecurityTokenInvalidIssuerException("IDX10212:"), Issuer = issClaim, - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidIssuer, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10212, LogHelper.MarkAsNonPII(issClaim), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validIssuers)), LogHelper.MarkAsNonPII(null)), + ValidationErrorType.SecurityTokenInvalidIssuer, + null, null), SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, issClaim), ValidationParameters = new ValidationParameters(), @@ -157,7 +160,7 @@ public IssuerValidationResultsTheoryData(string testId) : base(testId) public string Issuer { get; set; } - internal Result Result { get; set; } + internal Result Result { get; set; } public SecurityToken SecurityToken { get; set; } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs index 1b73e54e07..860c196d75 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs @@ -16,7 +16,7 @@ public void ValidateLifetime(ValidateLifetimeTheoryData theoryData) { CompareContext context = TestUtilities.WriteHeader($"{this}.LifetimeValidatorTests", theoryData); - Result result = Validators.ValidateLifetime( + Result result = Validators.ValidateLifetime( theoryData.NotBefore, theoryData.Expires, theoryData.SecurityToken, @@ -29,20 +29,13 @@ public void ValidateLifetime(ValidateLifetimeTheoryData theoryData) theoryData.Result.UnwrapResult(), result.UnwrapResult(), context); + + theoryData.ExpectedException.ProcessNoException(); } else { - IdentityComparer.AreTokenValidationErrorsEqual( - result.UnwrapError(), - theoryData.Result.UnwrapError(), - context); - - if (result.UnwrapError().InnerException is not null) - theoryData.ExpectedException.ProcessException(result.UnwrapError().InnerException); - else - theoryData.ExpectedException.ProcessNoException(); - - TestUtilities.AssertFailIfErrors(context); + Exception exception = result.UnwrapError().GetException(); + theoryData.ExpectedException.ProcessException(exception, context); } TestUtilities.AssertFailIfErrors(context); @@ -95,86 +88,99 @@ public static TheoryData ValidateLifetimeTestCases }, new ValidateLifetimeTheoryData("Invalid_ValidationParametersIsNull") { + ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), Expires = oneHourFromNow, NotBefore = oneHourAgo, ValidationParameters = null, - Result = new TokenValidationError( - ValidationErrorType.ArgumentNull, + Result = new ExceptionDetail( new MessageDetail(LogMessages.IDX10000, "validationParameters"), + ValidationErrorType.ArgumentNull, + null, null), }, new ValidateLifetimeTheoryData("Invalid_ExpiresIsNull") { + ExpectedException = ExpectedException.SecurityTokenNoExpirationException("IDX10225:"), NotBefore = oneHourAgo, ValidationParameters = new ValidationParameters(), - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenNoExpiration, + Result = new ExceptionDetail( new MessageDetail(LogMessages.IDX10225, "null"), + ValidationErrorType.SecurityTokenNoExpiration, + null, null), }, new ValidateLifetimeTheoryData("Invalid_NotBeforeIsAfterExpires") { + ExpectedException = ExpectedException.SecurityTokenInvalidLifetimeException("IDX10224:"), Expires = oneHourAgo, NotBefore = oneHourFromNow, ValidationParameters = new ValidationParameters(), - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidLifetime, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10224, LogHelper.MarkAsNonPII(oneHourFromNow), LogHelper.MarkAsNonPII(oneHourAgo)), + ValidationErrorType.SecurityTokenInvalidLifetime, + null, null), }, new ValidateLifetimeTheoryData("Invalid_NotYetValid") { + ExpectedException = ExpectedException.SecurityTokenNotYetValidException("IDX10222:"), Expires = twoHoursFromNow, NotBefore = oneHourFromNow, ValidationParameters = new ValidationParameters(), - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenNotYetValid, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10222, LogHelper.MarkAsNonPII(oneHourFromNow), LogHelper.MarkAsNonPII(now)), + ValidationErrorType.SecurityTokenNotYetValid, + null, null), }, new ValidateLifetimeTheoryData("Invalid_Expired") { + ExpectedException = ExpectedException.SecurityTokenExpiredException("IDX10223:"), Expires = oneHourAgo, NotBefore = twoHoursAgo, ValidationParameters = new ValidationParameters(), - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenExpired, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10223, LogHelper.MarkAsNonPII(oneHourAgo), LogHelper.MarkAsNonPII(now)), + ValidationErrorType.SecurityTokenExpired, + null, null), }, new ValidateLifetimeTheoryData("Invalid_NotYetValid_SkewForward") { + ExpectedException = ExpectedException.SecurityTokenNotYetValidException("IDX10222:"), Expires = oneHourFromNow, NotBefore = sixMinutesFromNow, ValidationParameters = new ValidationParameters { ClockSkew = TimeSpan.FromMinutes(5) }, - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenNotYetValid, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10222, LogHelper.MarkAsNonPII(sixMinutesFromNow), LogHelper.MarkAsNonPII(now)), + ValidationErrorType.SecurityTokenNotYetValid, + null, null), }, new ValidateLifetimeTheoryData("Invalid_Expired_SkewBackward") { + ExpectedException = ExpectedException.SecurityTokenExpiredException("IDX10223:"), Expires = sixMinutesAgo, NotBefore = twoHoursAgo, ValidationParameters = new ValidationParameters { ClockSkew = TimeSpan.FromMinutes(5) }, - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenExpired, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10223, LogHelper.MarkAsNonPII(sixMinutesAgo), LogHelper.MarkAsNonPII(now)), + ValidationErrorType.SecurityTokenExpired, null), } }; @@ -196,7 +202,7 @@ public ValidateLifetimeTheoryData(string testId) : base(testId) internal ValidationParameters ValidationParameters { get; set; } - internal Result Result { get; set; } + internal Result Result { get; set; } internal ValidationFailureType ValidationFailureType { get; set; } } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs index 137fc6c329..a2653a131b 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs @@ -16,7 +16,7 @@ public void ValidateTokenReplay(TokenReplayTheoryData theoryData) { CompareContext context = TestUtilities.WriteHeader($"{this}.TokenReplayValidationResultTests", theoryData); - Result result = Validators.ValidateTokenReplay( + Result result = Validators.ValidateTokenReplay( theoryData.ExpirationTime, theoryData.SecurityToken, theoryData.ValidationParameters, @@ -29,18 +29,13 @@ public void ValidateTokenReplay(TokenReplayTheoryData theoryData) theoryData.Result.UnwrapResult(), 1, context); + + theoryData.ExpectedException.ProcessNoException(); } else { - IdentityComparer.AreTokenValidationErrorsEqual( - result.UnwrapError(), - theoryData.Result.UnwrapError(), - context); - - if (result.UnwrapError().InnerException is not null) - theoryData.ExpectedException.ProcessException(result.UnwrapError().InnerException); - else - theoryData.ExpectedException.ProcessNoException(); + Exception exception = result.UnwrapError().GetException(); + theoryData.ExpectedException.ProcessException(exception, context); } TestUtilities.AssertFailIfErrors(context); @@ -81,45 +76,52 @@ public static TheoryData TokenReplayValidationTestCases new TokenReplayTheoryData { TestId = "Invalid_SecurityToken_Null", + ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), ExpirationTime = now, SecurityToken = null, ValidationParameters = new ValidationParameters(), - Result = new TokenValidationError( - ValidationErrorType.ArgumentNull, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), + ValidationErrorType.ArgumentNull, + null, null), }, new TokenReplayTheoryData { TestId = "Invalid_SecurityToken_Empty", + ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), ExpirationTime = now, SecurityToken = string.Empty, ValidationParameters = new ValidationParameters(), - Result = new TokenValidationError( - ValidationErrorType.ArgumentNull, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), + ValidationErrorType.ArgumentNull, + null, null), }, new TokenReplayTheoryData { TestId = "Invalid_ValidationParameters_Null", + ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), ExpirationTime = now, SecurityToken = "token", ValidationParameters = null, - Result = new TokenValidationError( - ValidationErrorType.ArgumentNull, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), + ValidationErrorType.ArgumentNull, + null, null), }, new TokenReplayTheoryData { TestId = "Invalid_ReplayCacheIsPresent_ExpirationTimeIsNull", + ExpectedException = ExpectedException.SecurityTokenReplayDetected("IDX10227:"), ExpirationTime = null, SecurityToken = "token", ValidationParameters = new ValidationParameters @@ -130,16 +132,18 @@ public static TheoryData TokenReplayValidationTestCases OnFindReturnValue = false } }, - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenReplayDetected, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10227, LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), + ValidationErrorType.SecurityTokenReplayDetected, + null, null), }, new TokenReplayTheoryData { TestId = "Invalid_ReplayCacheIsPresent_TokenIsAlreadyInCache", + ExpectedException = ExpectedException.SecurityTokenReplayDetected("IDX10228:"), ExpirationTime = oneHourFromNow, SecurityToken= "token", ValidationParameters = new ValidationParameters @@ -150,11 +154,12 @@ public static TheoryData TokenReplayValidationTestCases OnFindReturnValue = true }, }, - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenReplayDetected, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10228, LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), + ValidationErrorType.SecurityTokenReplayDetected, + null, null), }, new TokenReplayTheoryData @@ -171,11 +176,12 @@ public static TheoryData TokenReplayValidationTestCases } }, ExpectedException = ExpectedException.SecurityTokenReplayAddFailed("IDX10229:"), - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenReplayDetected, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10229, LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), + ValidationErrorType.SecurityTokenReplayDetected, + null, null), } }; @@ -191,6 +197,6 @@ public class TokenReplayTheoryData : TheoryDataBase internal ValidationParameters ValidationParameters { get; set; } - internal Result Result { get; set; } + internal Result Result { get; set; } } } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs index eb4041e147..f81ee3e04f 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs @@ -17,7 +17,7 @@ public void SecurityKey(SigningKeyValidationTheoryData theoryData) { CompareContext context = TestUtilities.WriteHeader($"{this}.SigningKeyValidationResultTests", theoryData); - Result result = Validators.ValidateIssuerSigningKey( + Result result = Validators.ValidateIssuerSigningKey( theoryData.SecurityKey, theoryData.SecurityToken, theoryData.ValidationParameters, @@ -30,18 +30,13 @@ public void SecurityKey(SigningKeyValidationTheoryData theoryData) theoryData.Result.UnwrapResult(), result.UnwrapResult(), context); + + theoryData.ExpectedException.ProcessNoException(); } else { - IdentityComparer.AreTokenValidationErrorsEqual( - result.UnwrapError(), - theoryData.Result.UnwrapError(), - context); - - if (result.UnwrapError().InnerException is not null) - theoryData.ExpectedException.ProcessException(result.UnwrapError().InnerException); - else - theoryData.ExpectedException.ProcessNoException(); + Exception exception = result.UnwrapError().GetException(); + theoryData.ExpectedException.ProcessException(exception, context); } TestUtilities.AssertFailIfErrors(context); @@ -68,78 +63,89 @@ public static TheoryData SigningKeyValidationTes new SigningKeyValidationTheoryData { TestId = "Invalid_SecurityKeyIsNull", + ExpectedException = ExpectedException.ArgumentNullException(substringExpected: "IDX10253:"), SecurityKey = null, SecurityToken = new JwtSecurityToken(), ValidationParameters = new ValidationParameters(), - Result = new TokenValidationError( - ValidationErrorType.ArgumentNull, + Result = new ExceptionDetail( new MessageDetail(LogMessages.IDX10253), + ValidationErrorType.ArgumentNull, + null, null), }, new SigningKeyValidationTheoryData { TestId = "Invalid_SecurityTokenIsNull", + ExpectedException = ExpectedException.ArgumentNullException(substringExpected: "IDX10000:"), SecurityKey = KeyingMaterial.SymmetricSecurityKey2_256, SecurityToken = null, ValidationParameters = new ValidationParameters (), - Result = new TokenValidationError( - ValidationErrorType.ArgumentNull, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), + ValidationErrorType.ArgumentNull, + null, null), }, new SigningKeyValidationTheoryData { TestId = "Invalid_ValidationParametersIsNull", + ExpectedException = ExpectedException.ArgumentNullException(substringExpected: "IDX10000:"), SecurityKey = KeyingMaterial.SymmetricSecurityKey2_256, SecurityToken = new JwtSecurityToken(), ValidationParameters = null, - Result = new TokenValidationError( - ValidationErrorType.ArgumentNull, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), + ValidationErrorType.ArgumentNull, + null, null), }, new SigningKeyValidationTheoryData { TestId = "Invalid_SecurityKeyIsExpired", + ExpectedException = ExpectedException.SecurityTokenInvalidSigningKeyException(substringExpected: "IDX10249:"), SecurityKey = KeyingMaterial.ExpiredX509SecurityKey_Public, SecurityToken = new JwtSecurityToken(), ValidationParameters = new ValidationParameters (), - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidSigningKey, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10249, LogHelper.MarkAsNonPII(utcExpired), LogHelper.MarkAsNonPII(utcNow)), + ValidationErrorType.SecurityTokenInvalidSigningKey, + null, null), }, new SigningKeyValidationTheoryData { TestId = "Invalid_SecurityKeyIsNotYetValid", + ExpectedException = ExpectedException.SecurityTokenInvalidSigningKeyException(substringExpected: "IDX10248:"), SecurityKey = KeyingMaterial.NotYetValidX509SecurityKey_Public, SecurityToken = new JwtSecurityToken(), ValidationParameters = new ValidationParameters (), - Result = new TokenValidationError( - ValidationErrorType.SecurityTokenInvalidSigningKey, + Result = new ExceptionDetail( new MessageDetail( LogMessages.IDX10248, LogHelper.MarkAsNonPII(utcNotYetValid), LogHelper.MarkAsNonPII(utcNow)), + ValidationErrorType.SecurityTokenInvalidSigningKey, + null, null), }, new SigningKeyValidationTheoryData { TestId = "Invalid_SecurityKeyIsNull", - ExpectedException = ExpectedException.ArgumentNullException(substringExpected: "IDX10253:"), + ExpectedException = ExpectedException.ArgumentNullException("IDX10253:"), SecurityKey = null, SecurityToken = new JwtSecurityToken(), ValidationParameters = new ValidationParameters (), - Result = new TokenValidationError( - ValidationErrorType.ArgumentNull, + Result = new ExceptionDetail( new MessageDetail(LogMessages.IDX10253), + ValidationErrorType.ArgumentNull, + null, null), }, @@ -154,6 +160,6 @@ public class SigningKeyValidationTheoryData : TheoryDataBase public SecurityToken SecurityToken { get; set; } internal ValidationParameters ValidationParameters { get; set; } public BaseConfiguration BaseConfiguration { get; set; } - internal Result Result { get; set; } + internal Result Result { get; set; } } } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs index c505875577..3374f45ddc 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.TestUtils; using Microsoft.IdentityModel.Tokens.Json.Tests; using Microsoft.IdentityModel.JsonWebTokens; @@ -24,21 +25,26 @@ public void ValidateTokenType(TokenTypeTheoryData theoryData) theoryData.ValidationParameters.ValidTypes.Add(tokenType); } - TokenTypeValidationResult tokenTypeValidationResult = Validators.ValidateTokenType( + Result result = Validators.ValidateTokenType( theoryData.Type, theoryData.SecurityToken, theoryData.ValidationParameters, new CallContext()); - if (tokenTypeValidationResult.Exception != null) - theoryData.ExpectedException.ProcessException(tokenTypeValidationResult.Exception); - else - theoryData.ExpectedException.ProcessNoException(); + if (result.IsSuccess) + { + IdentityComparer.AreValidatedTokenTypesEqual( + result.UnwrapResult(), + theoryData.Result.UnwrapResult(), + context); - IdentityComparer.AreTokenTypeValidationResultsEqual( - tokenTypeValidationResult, - theoryData.TokenTypeValidationResult, - context); + theoryData.ExpectedException.ProcessNoException(); + } + else + { + Exception exception = result.UnwrapError().GetException(); + theoryData.ExpectedException.ProcessException(exception, context); + } TestUtilities.AssertFailIfErrors(context); @@ -60,7 +66,7 @@ public static TheoryData TokenTypeValidationTestCases SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Typ, "JWT"), ValidationParameters = new ValidationParameters(), TokenTypesToAdd = validTypesWithJwt, - TokenTypeValidationResult = new TokenTypeValidationResult("JWT") + Result = new ValidatedTokenType("JWT", 4) }, new TokenTypeTheoryData { @@ -69,14 +75,13 @@ public static TheoryData TokenTypeValidationTestCases Type = "JWT", SecurityToken = null, ValidationParameters = null, - TokenTypeValidationResult = new TokenTypeValidationResult( - "JWT", - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII("securityToken")), - ExceptionDetail.ExceptionType.ArgumentNull)) + Result = new ExceptionDetail( + new MessageDetail( + LogMessages.IDX10000, + LogHelper.MarkAsNonPII("securityToken")), + ValidationErrorType.ArgumentNull, + null, + null) }, new TokenTypeTheoryData { @@ -85,14 +90,13 @@ public static TheoryData TokenTypeValidationTestCases Type = "JWT", SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Typ, "JWT"), ValidationParameters = null, - TokenTypeValidationResult = new TokenTypeValidationResult( - "JWT", - ValidationFailureType.NullArgument, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10000, - LogHelper.MarkAsNonPII("validationParameters")), - ExceptionDetail.ExceptionType.ArgumentNull)) + Result = new ExceptionDetail( + new MessageDetail( + LogMessages.IDX10000, + LogHelper.MarkAsNonPII("validationParameters")), + ValidationErrorType.ArgumentNull, + null, + null) }, new TokenTypeTheoryData { @@ -102,14 +106,13 @@ public static TheoryData TokenTypeValidationTestCases SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Typ, String.Empty), ValidationParameters = new ValidationParameters(), TokenTypesToAdd = validTypesNoJwt, - TokenTypeValidationResult = new TokenTypeValidationResult( - string.Empty, - ValidationFailureType.TokenTypeValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10256, - LogHelper.MarkAsNonPII("type")), - ExceptionDetail.ExceptionType.SecurityTokenInvalidType)) + Result = new ExceptionDetail( + new MessageDetail( + LogMessages.IDX10256, + LogHelper.MarkAsNonPII("type")), + ValidationErrorType.SecurityTokenInvalidType, + null, + null) }, new TokenTypeTheoryData { @@ -119,14 +122,13 @@ public static TheoryData TokenTypeValidationTestCases SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Typ, null), ValidationParameters = new ValidationParameters(), TokenTypesToAdd = validTypesNoJwt, - TokenTypeValidationResult = new TokenTypeValidationResult( + Result = new ExceptionDetail( + new MessageDetail( + LogMessages.IDX10256, + LogHelper.MarkAsNonPII("type")), + ValidationErrorType.SecurityTokenInvalidType, null, - ValidationFailureType.TokenTypeValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10256, - LogHelper.MarkAsNonPII("type")), - ExceptionDetail.ExceptionType.SecurityTokenInvalidType)) + null) }, new TokenTypeTheoryData { @@ -136,15 +138,14 @@ public static TheoryData TokenTypeValidationTestCases SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Typ, "JWT"), ValidationParameters = new ValidationParameters(), TokenTypesToAdd = validTypesNoJwt, - TokenTypeValidationResult = new TokenTypeValidationResult( - "JWT", - ValidationFailureType.TokenTypeValidationFailed, - new ExceptionDetail( - new MessageDetail( - LogMessages.IDX10257, - LogHelper.MarkAsNonPII("type"), - LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validTypesNoJwt))), - ExceptionDetail.ExceptionType.SecurityTokenInvalidType)) + Result = new ExceptionDetail( + new MessageDetail( + LogMessages.IDX10257, + LogHelper.MarkAsNonPII("type"), + LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validTypesNoJwt))), + ValidationErrorType.SecurityTokenInvalidType, + null, + null) } }; } @@ -157,8 +158,7 @@ public class TokenTypeTheoryData : TheoryDataBase public SecurityToken SecurityToken { get; set; } public IList TokenTypesToAdd { get; internal set; } internal ValidationParameters ValidationParameters { get; set; } - - internal TokenTypeValidationResult TokenTypeValidationResult { get; set; } + internal Result Result { get; set; } } } } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ValidationParametersTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ValidationParametersTests.cs index 7cc0afc899..99b6f8713b 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ValidationParametersTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ValidationParametersTests.cs @@ -42,7 +42,7 @@ public void ValidAudiences_Get_ReturnsEmptyList() public void ValidTypes_Get_ReturnsEmptyList() { var validationParameters = new ValidationParameters(); - + Assert.Equal(0, validationParameters.ValidTypes.Count); Assert.True(validationParameters.ValidTypes is IList); } From 50174013150bd4b76ae45100c4b2e7e0d19e71f1 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Fri, 23 Aug 2024 17:20:01 +0100 Subject: [PATCH 15/32] Added ClaimsIdentity to ValidationResult --- .../Validation/Results/ValidationResult.cs | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs index fc1a8a4577..6eaf7eddb9 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs @@ -3,7 +3,10 @@ #nullable enable using System; +using System.Collections.Generic; using System.Diagnostics; +using System.Security.Claims; +using System.Threading; namespace Microsoft.IdentityModel.Tokens { @@ -81,6 +84,113 @@ public void Log() public ValidatedSigningKeyLifetime? ValidatedSigningKeyLifetime { get; internal set; } #endregion + #region Claims + // Fields lazily initialized in a thread-safe manner. _claimsIdentity is protected by the _claimsIdentitySyncObj + // lock, and since null is a valid initialized value, _claimsIdentityInitialized tracks whether or not it's valid. + // _claims is constructed by reading the data from the ClaimsIdentity and is synchronized using Interlockeds + // to ensure only one dictionary is published in the face of concurrent access (but if there's a race condition, + // multiple dictionaries could be constructed, with only one published for all to see). Simiarly, _propertyBag + // is initalized with Interlocked to ensure only a single instance is published in the face of concurrent use. + // _claimsIdentityInitialized only ever transitions from false to true, and is volatile to reads/writes are not + // reordered relative to the other operations. The rest of the objects are not because the .NET memory model + // guarantees object writes are store releases and that reads won't be introduced. + private volatile bool _claimsIdentityInitialized; + private object? _claimsIdentitySyncObj; + private ClaimsIdentity? _claimsIdentity; + private Dictionary? _claims; + + /// + /// The created from the validated security token. + /// + public IDictionary? Claims + { + get + { + if (_claims is null && ClaimsIdentity is not null) + { + Interlocked.CompareExchange(ref _claims, TokenUtilities.CreateDictionaryFromClaims(ClaimsIdentity.Claims), null); + } + + return _claims; + } + } + + /// + /// The created from the validated security token. + /// + public ClaimsIdentity ClaimsIdentity + { + get + { + if (!_claimsIdentityInitialized) + { + lock (ClaimsIdentitySyncObj) + { + return ClaimsIdentityNoLocking; + } + } + + return _claimsIdentity!; + } + set + { + if (value is null) + throw new ArgumentNullException(nameof(value), "ClaimsIdentity cannot be set as null."); + + lock (ClaimsIdentitySyncObj) + { + ClaimsIdentityNoLocking = value; + } + } + } + + /// + /// Gets or sets the without synchronization. All accesses must either + /// be protected or used when the caller knows access is serialized. + /// + internal ClaimsIdentity ClaimsIdentityNoLocking + { + get + { + if (!_claimsIdentityInitialized) + { + Debug.Assert(_claimsIdentity is null); + + if (IsValid) + { + _claimsIdentity = TokenHandler.CreateClaimsIdentityInternal(SecurityToken, ValidationParameters, ValidatedIssuer.Issuer); + } + + _claimsIdentityInitialized = true; + } + + return _claimsIdentity!; + } + set + { + Debug.Assert(value is not null); + _claimsIdentity = value; + _claims = null; + _claimsIdentityInitialized = true; + } + } + + /// Gets the object to use in for double-checked locking. + private object ClaimsIdentitySyncObj + { + get + { + object? syncObj = _claimsIdentitySyncObj; + if (syncObj is null) + { + Interlocked.CompareExchange(ref _claimsIdentitySyncObj, new object(), null); + syncObj = _claimsIdentitySyncObj; + } + + return syncObj; + } + } + #endregion } } #nullable disable From 90fce75f2986948a43e33adda55a7e47a3e2c68e Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Fri, 23 Aug 2024 17:50:52 +0100 Subject: [PATCH 16/32] Updated benchmarks to match the result types and added CancellationToken --- .../Program.cs | 2 +- .../ValidateTokenAsyncTests.cs | 35 ++++++++---- ...TokenAsyncWithValidationParametersTests.cs | 56 ++++++++++--------- 3 files changed, 54 insertions(+), 39 deletions(-) diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/Program.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/Program.cs index 570a92b9af..5c33334a49 100644 --- a/benchmark/Microsoft.IdentityModel.Benchmarks/Program.cs +++ b/benchmark/Microsoft.IdentityModel.Benchmarks/Program.cs @@ -49,7 +49,7 @@ private static void DebugThroughTests() ValidateTokenAsyncTests validateTokenAsyncTests = new ValidateTokenAsyncTests(); validateTokenAsyncTests.Setup(); TokenValidationResult tokenValidationResult = validateTokenAsyncTests.JsonWebTokenHandler_ValidateTokenAsyncWithTVP().Result; - TokenValidationResult validationResult = validateTokenAsyncTests.JsonWebTokenHandler_ValidateTokenAsyncWithVP().Result; + bool validationResult = validateTokenAsyncTests.JsonWebTokenHandler_ValidateTokenAsyncWithVP().Result; var claims = validateTokenAsyncTests.JsonWebTokenHandler_ValidateTokenAsyncWithTVP_CreateClaims(); ValidateSignedHttpRequestAsyncTests validateSignedHttpRequestAsyncTests = new ValidateSignedHttpRequestAsyncTests(); diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncTests.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncTests.cs index 8724b49637..f4cb373d54 100644 --- a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncTests.cs +++ b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncTests.cs @@ -5,6 +5,7 @@ using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; +using System.Threading; using System.Threading.Tasks; using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; @@ -143,30 +144,40 @@ public async Task JsonWebTokenHandler_ValidateTokenAsyncW } [BenchmarkCategory("ValidateTokenAsyncWithValidationParameters"), Benchmark(Baseline = true)] - public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP() + { + // Because ValidationResult is an internal type, we cannot return it in the benchmark. + // We return a boolean instead until the type is made public. + ValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + return result.IsValid; + } [BenchmarkCategory("ValidateTokenAsyncWithValidationParameters"), Benchmark] - public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP_SucceedOnThirdAttempt() + public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP_SucceedOnThirdAttempt() { - var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - return await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + ValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + + return result.IsValid; } [BenchmarkCategory("ValidateTokenAsyncWithValidationParameters"), Benchmark] - public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP_SucceedOnFifthAttempt() + public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP_SucceedOnFifthAttempt() { - var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - return await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + ValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + + return result.IsValid; } [BenchmarkCategory("ValidateTokenAsyncClaimAccess"), Benchmark] public async Task> JsonWebTokenHandler_ValidateTokenAsyncWithVP_CreateClaims() { - var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); var claimsIdentity = result.ClaimsIdentity; var claims = claimsIdentity.Claims; return claims.ToList(); diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs index 7cbe45111c..daed66cdb6 100644 --- a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs +++ b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs @@ -1,6 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading; using System.Threading.Tasks; using BenchmarkDotNet.Attributes; using Microsoft.IdentityModel.JsonWebTokens; @@ -83,7 +87,7 @@ public void Setup() public async Task JsonWebTokenHandler_02_ValidateTokenAsyncWithTVPUsingClone() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false) != null; [Benchmark] - public async Task JsonWebTokenHandler_03_ValidateTokenAsyncWithVP() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false) != null; + public async Task JsonWebTokenHandler_03_ValidateTokenAsyncWithVP() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false) != null; [Benchmark] public async Task JsonWebTokenHandler_04_ValidateTokenAsyncWithTVP_SucceedOnThirdAttempt() @@ -108,9 +112,9 @@ public async Task JsonWebTokenHandler_05_ValidateTokenAsyncWithTVPUsingClo [Benchmark] public async Task JsonWebTokenHandler_06_ValidateTokenAsyncWithVP_SucceedOnThirdAttempt() { - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); return true; } @@ -142,31 +146,31 @@ public async Task JsonWebTokenHandler_08_ValidateTokenAsyncWithTVPUsingClo [Benchmark] public async Task JsonWebTokenHandler_09_ValidateTokenAsyncWithVP_SucceedOnFifthAttempt() { - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, null).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); return true; } - //[Benchmark] - //public async Task> JsonWebTokenHandler_10_ValidateTokenAsyncWithTVP_CreateClaims() - //{ - // var await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false); - // var claimsIdentity = result.ClaimsIdentity; - // var claims = claimsIdentity.Claims; - // return claims.ToList(); - //} - - //[Benchmark] - //public async Task> JsonWebTokenHandler_11_ValidateTokenAsyncWithVP_CreateClaims() - //{ - // var await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, null).ConfigureAwait(false); - // var claimsIdentity = result.ClaimsIdentity; - // var claims = claimsIdentity.Claims; - // return claims.ToList(); - //} + [Benchmark] + public async Task> JsonWebTokenHandler_10_ValidateTokenAsyncWithTVP_CreateClaims() + { + var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false); + var claimsIdentity = result.ClaimsIdentity; + var claims = claimsIdentity.Claims; + return claims.ToList(); + } + + [Benchmark] + public async Task> JsonWebTokenHandler_11_ValidateTokenAsyncWithVP_CreateClaims() + { + var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + var claimsIdentity = result.ClaimsIdentity; + var claims = claimsIdentity.Claims; + return claims.ToList(); + } } } From 09bc19880bc6e1396b77d2df8e06e7b84a7a644b Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Fri, 23 Aug 2024 18:42:48 +0100 Subject: [PATCH 17/32] Removed test consoleapp, re-grouped benchmarks for better comparison --- ConsoleApp1/ConsoleApp1.csproj | 19 -- ConsoleApp1/Program.cs | 17 -- Wilson.sln | 9 - .../ValidateTokenAsyncTests.cs | 68 +++---- ...TokenAsyncWithValidationParametersTests.cs | 176 ------------------ 5 files changed, 34 insertions(+), 255 deletions(-) delete mode 100644 ConsoleApp1/ConsoleApp1.csproj delete mode 100644 ConsoleApp1/Program.cs delete mode 100644 benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs diff --git a/ConsoleApp1/ConsoleApp1.csproj b/ConsoleApp1/ConsoleApp1.csproj deleted file mode 100644 index e6b6b29bd2..0000000000 --- a/ConsoleApp1/ConsoleApp1.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - Exe - net8.0 - enable - enable - true - true - True - C:\Users\iinglese\OneDrive - Microsoft\Desktop\ConsoleApp1.snk - - - - - - - - diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs deleted file mode 100644 index 13b6e5de93..0000000000 --- a/ConsoleApp1/Program.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Microsoft.IdentityModel.Benchmarks; - -Console.WriteLine("Hello, World!"); - -var test = new ValidateTokenAsyncWithVPTests(); -test.Setup(); - -var list = new List(); -Console.WriteLine("Size of list: " + list.Capacity); - -for (int i = 0; i < 1000; i++) -{ - await test.JsonWebTokenHandler_03_ValidateTokenAsyncWithVP(); -} diff --git a/Wilson.sln b/Wilson.sln index 7aec0fce85..512a3f8404 100644 --- a/Wilson.sln +++ b/Wilson.sln @@ -109,11 +109,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{BC99A01F build\version.props = build\version.props EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp1", "ConsoleApp1\ConsoleApp1.csproj", "{DA52E36D-588B-4DF9-A2DD-3442E87938FA}" - ProjectSection(ProjectDependencies) = postProject - {DBF58792-25DF-4B6E-866C-77A0BC5AB81B} = {DBF58792-25DF-4B6E-866C-77A0BC5AB81B} - EndProjectSection -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -244,10 +239,6 @@ Global {F1BB31E4-8865-4425-8BD4-94F1815C16E0}.Debug|Any CPU.Build.0 = Debug|Any CPU {F1BB31E4-8865-4425-8BD4-94F1815C16E0}.Release|Any CPU.ActiveCfg = Release|Any CPU {F1BB31E4-8865-4425-8BD4-94F1815C16E0}.Release|Any CPU.Build.0 = Release|Any CPU - {DA52E36D-588B-4DF9-A2DD-3442E87938FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DA52E36D-588B-4DF9-A2DD-3442E87938FA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DA52E36D-588B-4DF9-A2DD-3442E87938FA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DA52E36D-588B-4DF9-A2DD-3442E87938FA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncTests.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncTests.cs index f4cb373d54..d2659e3b1c 100644 --- a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncTests.cs +++ b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncTests.cs @@ -83,13 +83,13 @@ public void Setup() _callContext = new CallContext(); } - [BenchmarkCategory("ValidateTokenAsyncWithTokenValidationParameters"), Benchmark] - public async Task JwtSecurityTokenHandler_ValidateTokenAsync() => await _jwtSecurityTokenHandler.ValidateTokenAsync(_jws, _tokenValidationParameters).ConfigureAwait(false); + [BenchmarkCategory("ValidateTokenAsync_Success"), Benchmark] + public async Task JwtSecurityTokenHandler_ValidateTokenAsync() => await _jwtSecurityTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); - [BenchmarkCategory("ValidateTokenAsyncWithTokenValidationParameters"), Benchmark(Baseline = true)] - public async Task JsonWebTokenHandler_ValidateTokenAsyncWithTVP() => await _jsonWebTokenHandler.ValidateTokenAsync(_jws, _tokenValidationParameters).ConfigureAwait(false); + [BenchmarkCategory("ValidateTokenAsync_Success"), Benchmark(Baseline = true)] + public async Task JsonWebTokenHandler_ValidateTokenAsyncWithTVP() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); - [BenchmarkCategory("ValidateTokenAsyncWithTokenValidationParameters"), Benchmark] + [BenchmarkCategory("ValidateTokenAsync_Success"), Benchmark] public async Task JsonWebTokenHandler_ValidateTokenAsyncWithTVPUsingModifiedClone() { var tokenValidationParameters = _tokenValidationParameters.Clone(); @@ -99,7 +99,16 @@ public async Task JsonWebTokenHandler_ValidateTokenAsyncW return await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, tokenValidationParameters).ConfigureAwait(false); } - [BenchmarkCategory("ValidateTokenAsyncWithTokenValidationParameters"), Benchmark] + [BenchmarkCategory("ValidateTokenAsync_Success"), Benchmark] + public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP() + { + // Because ValidationResult is an internal type, we cannot return it in the benchmark. + // We return a boolean instead until the type is made public. + ValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + return result.IsValid; + } + + [BenchmarkCategory("ValidateTokenAsync_FailTwiceBeforeSuccess"), Benchmark(Baseline = true)] public async Task JsonWebTokenHandler_ValidateTokenAsyncWithTVP_SucceedOnThirdAttempt() { TokenValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); @@ -109,7 +118,7 @@ public async Task JsonWebTokenHandler_ValidateTokenAsyncW return result; } - [BenchmarkCategory("ValidateTokenAsyncWithTokenValidationParameters"), Benchmark] + [BenchmarkCategory("ValidateTokenAsync_FailTwiceBeforeSuccess"), Benchmark] public async Task JsonWebTokenHandler_ValidateTokenAsyncWithTVPUsingClone_SucceedOnThirdAttempt() { TokenValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); @@ -119,7 +128,17 @@ public async Task JsonWebTokenHandler_ValidateTokenAsyncW return result; } - [BenchmarkCategory("ValidateTokenAsyncWithTokenValidationParameters"), Benchmark] + [BenchmarkCategory("ValidateTokenAsync_FailTwiceBeforeSuccess"), Benchmark] + public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP_SucceedOnThirdAttempt() + { + ValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + + return result.IsValid; + } + + [BenchmarkCategory("ValidateTokenAsync_FailFourTimesBeforeSuccess"), Benchmark(Baseline = true)] public async Task JsonWebTokenHandler_ValidateTokenAsyncWithTVP_SucceedOnFifthAttempt() { TokenValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); @@ -131,7 +150,7 @@ public async Task JsonWebTokenHandler_ValidateTokenAsyncW return result; } - [BenchmarkCategory("ValidateTokenAsyncWithTokenValidationParameters"), Benchmark] + [BenchmarkCategory("ValidateTokenAsync_FailFourTimesBeforeSuccess"), Benchmark] public async Task JsonWebTokenHandler_ValidateTokenAsyncWithTVPUsingClone_SucceedOnFifthAttempt() { TokenValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); @@ -143,26 +162,7 @@ public async Task JsonWebTokenHandler_ValidateTokenAsyncW return result; } - [BenchmarkCategory("ValidateTokenAsyncWithValidationParameters"), Benchmark(Baseline = true)] - public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP() - { - // Because ValidationResult is an internal type, we cannot return it in the benchmark. - // We return a boolean instead until the type is made public. - ValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - return result.IsValid; - } - - [BenchmarkCategory("ValidateTokenAsyncWithValidationParameters"), Benchmark] - public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP_SucceedOnThirdAttempt() - { - ValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - - return result.IsValid; - } - - [BenchmarkCategory("ValidateTokenAsyncWithValidationParameters"), Benchmark] + [BenchmarkCategory("ValidateTokenAsync_FailFourTimesBeforeSuccess"), Benchmark] public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP_SucceedOnFifthAttempt() { ValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); @@ -174,19 +174,19 @@ public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP_SucceedOnFi return result.IsValid; } - [BenchmarkCategory("ValidateTokenAsyncClaimAccess"), Benchmark] - public async Task> JsonWebTokenHandler_ValidateTokenAsyncWithVP_CreateClaims() + [BenchmarkCategory("ValidateTokenAsyncClaimAccess"), Benchmark(Baseline = true)] + public async Task> JsonWebTokenHandler_ValidateTokenAsyncWithTVP_CreateClaims() { - var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); var claimsIdentity = result.ClaimsIdentity; var claims = claimsIdentity.Claims; return claims.ToList(); } [BenchmarkCategory("ValidateTokenAsyncClaimAccess"), Benchmark] - public async Task> JsonWebTokenHandler_ValidateTokenAsyncWithTVP_CreateClaims() + public async Task> JsonWebTokenHandler_ValidateTokenAsyncWithVP_CreateClaims() { - var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); + var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); var claimsIdentity = result.ClaimsIdentity; var claims = claimsIdentity.Claims; return claims.ToList(); diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs deleted file mode 100644 index daed66cdb6..0000000000 --- a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncWithValidationParametersTests.cs +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using System.Threading; -using System.Threading.Tasks; -using BenchmarkDotNet.Attributes; -using Microsoft.IdentityModel.JsonWebTokens; -using Microsoft.IdentityModel.Tokens; - -namespace Microsoft.IdentityModel.Benchmarks -{ - // dotnet run -c release -f net8.0 --filter Microsoft.IdentityModel.Benchmarks.ValidateTokenAsyncWithVPTests* - - public class ValidateTokenAsyncWithVPTests - { - private CallContext _callContext; - private JsonWebTokenHandler _jsonWebTokenHandler; - private SecurityTokenDescriptor _tokenDescriptor; - private SecurityTokenDescriptor _tokenDescriptorExtendedClaims; - private string _jws; - private string _jwsExtendedClaims; - private TokenValidationParameters _tokenValidationParameters; - private ValidationParameters _validationParameters; - private TokenValidationParameters _invalidTokenValidationParameters; - private ValidationParameters _invalidValidationParameters; - - [GlobalSetup] - public void Setup() - { - _tokenDescriptor = new SecurityTokenDescriptor - { - Claims = BenchmarkUtils.Claims, - SigningCredentials = BenchmarkUtils.SigningCredentialsRsaSha256, - }; - - _tokenDescriptorExtendedClaims = new SecurityTokenDescriptor - { - Claims = BenchmarkUtils.ClaimsExtendedExample, - SigningCredentials = BenchmarkUtils.SigningCredentialsRsaSha256, - }; - - _jsonWebTokenHandler = new JsonWebTokenHandler(); - _jws = _jsonWebTokenHandler.CreateToken(_tokenDescriptor); - _jwsExtendedClaims = _jsonWebTokenHandler.CreateToken(_tokenDescriptorExtendedClaims); - - _validationParameters = new ValidationParameters(); - _validationParameters.ValidAudiences.Add(BenchmarkUtils.Audience); - _validationParameters.ValidIssuers.Add(BenchmarkUtils.Issuer); - _validationParameters.IssuerSigningKeys.Add(BenchmarkUtils.SigningCredentialsRsaSha256.Key); - - _invalidValidationParameters = new ValidationParameters(); - _invalidValidationParameters.ValidAudiences.Add(BenchmarkUtils.Audience); - _invalidValidationParameters.ValidIssuers.Add(BenchmarkUtils.Issuer); - - _callContext = new CallContext(); - - _tokenValidationParameters = new TokenValidationParameters() - { - ValidAudience = BenchmarkUtils.Audience, - ValidateLifetime = true, - ValidIssuer = BenchmarkUtils.Issuer, - IssuerSigningKey = BenchmarkUtils.SigningCredentialsRsaSha256.Key, - ValidateIssuerSigningKey = true, - ValidateTokenReplay = true, - RequireSignedTokens = true, - ValidateSignatureLast = true - }; - - _invalidTokenValidationParameters = new TokenValidationParameters() - { - ValidAudience = BenchmarkUtils.Audience, - ValidateLifetime = true, - ValidIssuer = BenchmarkUtils.Issuer, - ValidateIssuerSigningKey = true, - ValidateTokenReplay = true, - ValidateSignatureLast = true - }; - } - - [Benchmark] - public async Task JsonWebTokenHandler_01_ValidateTokenAsyncWithTVP() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false) != null; - - [Benchmark] - public async Task JsonWebTokenHandler_02_ValidateTokenAsyncWithTVPUsingClone() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false) != null; - - [Benchmark] - public async Task JsonWebTokenHandler_03_ValidateTokenAsyncWithVP() => await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false) != null; - - [Benchmark] - public async Task JsonWebTokenHandler_04_ValidateTokenAsyncWithTVP_SucceedOnThirdAttempt() - { - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); - - return true; - } - - [Benchmark] - public async Task JsonWebTokenHandler_05_ValidateTokenAsyncWithTVPUsingClone_SucceedOnThirdAttempt() - { - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false); - - return true; - } - - [Benchmark] - public async Task JsonWebTokenHandler_06_ValidateTokenAsyncWithVP_SucceedOnThirdAttempt() - { - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - - return true; - } - - [Benchmark] - public async Task JsonWebTokenHandler_07_ValidateTokenAsyncWithTVP_SucceedOnFifthAttempt() - { - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); - - return true; - } - - [Benchmark] - public async Task JsonWebTokenHandler_08_ValidateTokenAsyncWithTVPUsingClone_SucceedOnFifthAttempt() - { - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidTokenValidationParameters.Clone()).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false); - - return true; - } - - [Benchmark] - public async Task JsonWebTokenHandler_09_ValidateTokenAsyncWithVP_SucceedOnFifthAttempt() - { - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - - return true; - } - - [Benchmark] - public async Task> JsonWebTokenHandler_10_ValidateTokenAsyncWithTVP_CreateClaims() - { - var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _tokenValidationParameters.Clone()).ConfigureAwait(false); - var claimsIdentity = result.ClaimsIdentity; - var claims = claimsIdentity.Claims; - return claims.ToList(); - } - - [Benchmark] - public async Task> JsonWebTokenHandler_11_ValidateTokenAsyncWithVP_CreateClaims() - { - var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - var claimsIdentity = result.ClaimsIdentity; - var claims = claimsIdentity.Claims; - return claims.ToList(); - } - } -} From 32dcd6dcd7f5ff25ab392059a1ef763b5032fded Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Fri, 23 Aug 2024 18:44:37 +0100 Subject: [PATCH 18/32] Removed unit type --- .../Unit.cs | 16 ---------------- .../UnitTests.cs | 19 ------------------- 2 files changed, 35 deletions(-) delete mode 100644 src/Microsoft.IdentityModel.Abstractions/Unit.cs delete mode 100644 test/Microsoft.IdentityModel.Abstractions.Tests/UnitTests.cs diff --git a/src/Microsoft.IdentityModel.Abstractions/Unit.cs b/src/Microsoft.IdentityModel.Abstractions/Unit.cs deleted file mode 100644 index 6132dc50f0..0000000000 --- a/src/Microsoft.IdentityModel.Abstractions/Unit.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -namespace Microsoft.IdentityModel.Abstractions -{ - /// - /// Unit type used to represent the absence of a specific value. - /// - public record struct Unit - { - /// - /// Returns the default instance of . - /// - public static Unit Default { get; } - } -} diff --git a/test/Microsoft.IdentityModel.Abstractions.Tests/UnitTests.cs b/test/Microsoft.IdentityModel.Abstractions.Tests/UnitTests.cs deleted file mode 100644 index eb18a9e259..0000000000 --- a/test/Microsoft.IdentityModel.Abstractions.Tests/UnitTests.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Xunit; - -namespace Microsoft.IdentityModel.Abstractions.Tests -{ - public class UnitTests - { - [Fact] - public void Unit_Default() - { - Assert.Equal(Unit.Default, Unit.Default); - Assert.True(Unit.Default == Unit.Default); - Assert.Equal(Unit.Default, new Unit()); - Assert.True(new Unit() == Unit.Default); - } - } -} From 72e9574b3d93456b371f7136432fa2e51ddab1c5 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Sun, 25 Aug 2024 20:31:54 +0100 Subject: [PATCH 19/32] Removed TokenValidationError since it is no longer used --- .../Results/Details/ExceptionDetail.cs | 27 ++++++ .../Results/TokenValidationError.cs | 89 ------------------- .../Results/TokenValidationResult.cs | 21 ++--- .../IdentityComparer.cs | 17 ---- 4 files changed, 36 insertions(+), 118 deletions(-) delete mode 100644 src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs index ba2e03ecf2..b9ff348217 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs @@ -132,4 +132,31 @@ public static Exception ExceptionFromType( } } } + + internal enum ValidationErrorType + { + Unknown = -1, + ArgumentNull, + InvalidArgument, + InvalidOperation, + SecurityToken, + SecurityTokenDecompressionFailed, + SecurityTokenDecryptionFailed, + SecurityTokenExpired, + SecurityTokenInvalidAudience, + SecurityTokenInvalidAlgorithm, + SecurityTokenInvalidIssuer, + SecurityTokenInvalidLifetime, + SecurityTokenInvalidSigningKey, + SecurityTokenInvalidSignature, + SecurityTokenInvalidType, + SecurityTokenKeyWrap, + SecurityTokenMalformed, + SecurityTokenNoExpiration, + SecurityTokenNotYetValid, + SecurityTokenReplayDetected, + SecurityTokenReplayAddFailed, + SecurityTokenSignatureKeyNotFound, + ExceptionTypeCount + } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs deleted file mode 100644 index e9683beff9..0000000000 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationError.cs +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace Microsoft.IdentityModel.Tokens -{ - internal class TokenValidationError - { - public ValidationErrorType ErrorType { get; } - public MessageDetail MessageDetail { get; } - public Exception? InnerException { get; } - public string CallerFilePath { get; } - public int CallerLineNumber { get; } - - private StackFrame? _stackFrame; - - public TokenValidationError( - ValidationErrorType errorType, - MessageDetail messageDetail, - Exception? innerException, - [CallerFilePath] string callerFilePath = "", - [CallerLineNumber] int callerLineNumber = 0 - ) - { - ErrorType = errorType; - MessageDetail = messageDetail; - InnerException = innerException; - CallerFilePath = callerFilePath; - CallerLineNumber = callerLineNumber; - - if (AppContextSwitches.DontFailOnMissingTid) - CallerLineNumber = 123; - - _stackFrame = new StackFrame(true); - } - } - - /// - /// - /// - public static class TokenValidationErrorCommon - { - /// - /// - /// - /// - /// - internal static TokenValidationError NullParameter( - string parameterName, -#pragma warning disable CS1573 // Parameter has no matching param tag in the XML comment (but other parameters do) - [CallerFilePath] string callerFilePath = "", - [CallerLineNumber] int callerLineNumber = 0) -#pragma warning restore CS1573 // Parameter has no matching param tag in the XML comment (but other parameters do) - => new(ValidationErrorType.ArgumentNull, MessageDetail.NullParameter(parameterName), null, callerFilePath, callerLineNumber); - } - - internal enum ValidationErrorType - { - Unknown = -1, - ArgumentNull, - InvalidArgument, - InvalidOperation, - SecurityToken, - SecurityTokenDecompressionFailed, - SecurityTokenDecryptionFailed, - SecurityTokenExpired, - SecurityTokenInvalidAudience, - SecurityTokenInvalidAlgorithm, - SecurityTokenInvalidIssuer, - SecurityTokenInvalidLifetime, - SecurityTokenInvalidSigningKey, - SecurityTokenInvalidSignature, - SecurityTokenInvalidType, - SecurityTokenKeyWrap, - SecurityTokenMalformed, - SecurityTokenNoExpiration, - SecurityTokenNotYetValid, - SecurityTokenReplayDetected, - SecurityTokenReplayAddFailed, - SecurityTokenSignatureKeyNotFound, - ExceptionTypeCount - } -} -#nullable restore diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationResult.cs index 44538236af..024f4230a7 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationResult.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationResult.cs @@ -37,7 +37,7 @@ public class TokenValidationResult // TODO - lazy creation of _validationResults private List _validationResults; - private TokenValidationError _tokenValidationError; + private ExceptionDetail _exceptionDetail; private Exception _exception; private bool _isValid; @@ -79,7 +79,7 @@ internal TokenValidationResult( /// /// /// - /// + /// /// This constructor is used by JsonWebTokenHandler as part of delaying creation of ClaimsIdentity. internal TokenValidationResult( SecurityToken securityToken, @@ -87,30 +87,30 @@ internal TokenValidationResult( ValidationParameters validationParameters, string issuer, List validationResults, - TokenValidationError tokenValidationError) + ExceptionDetail exceptionDetail) { _validationParameters = validationParameters; _tokenHandler = tokenHandler; _validationResults = validationResults; Issuer = issuer; SecurityToken = securityToken; - _tokenValidationError = tokenValidationError; + _exceptionDetail = exceptionDetail; } /// /// Initializes a new instance of using . /// /// - /// + /// /// /// This constructor is used by JsonWebTokenHandler as part of delaying creation of ClaimsIdentity. internal TokenValidationResult( TokenHandler tokenHandler, ValidationParameters validationParameters, - TokenValidationError tokenValidationError) + ExceptionDetail exceptionDetail) { _tokenHandler = tokenHandler; - _tokenValidationError = tokenValidationError; + _exceptionDetail = exceptionDetail; _validationParameters = validationParameters; } @@ -220,11 +220,8 @@ public Exception Exception get { HasValidOrExceptionWasRead = true; - if (_exception is null && _tokenValidationError is not null) - return ExceptionDetail.ExceptionFromType( - _tokenValidationError.ErrorType, - _tokenValidationError.MessageDetail, - null); + if (_exception is null && _exceptionDetail is not null) + return _exceptionDetail.GetException(); return _exception; } diff --git a/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs b/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs index c03a0b0afd..3eae6e2e32 100644 --- a/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs +++ b/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs @@ -1315,23 +1315,6 @@ internal static bool AreValidatedTokenTypesEqual(ValidatedTokenType validatedTok return context.Merge(localContext); } - internal static bool AreTokenValidationErrorsEqual(TokenValidationError tokenValidationError1, TokenValidationError tokenValidationError2, CompareContext context) - { - var localContext = new CompareContext(context); - - AreIntsEqual( - tokenValidationError1.ErrorType, - tokenValidationError2.ErrorType, - localContext); - - AreStringsEqual( - tokenValidationError1.MessageDetail.Message, - tokenValidationError2.MessageDetail.Message, - localContext); - - return context.Merge(localContext); - } - private static bool AreValueCollectionsEqual(Object object1, Object object2, CompareContext context) { Dictionary.ValueCollection vc1 = (Dictionary.ValueCollection)object1; From 925ee09bb5fddc4a944a3cb9f6e437847d8b8fe6 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Sun, 25 Aug 2024 20:36:03 +0100 Subject: [PATCH 20/32] Restored ExceptionType type name --- .../JsonWebTokenHandler.DecryptToken.cs | 6 +-- .../JsonWebTokenHandler.ReadToken.cs | 2 +- .../JsonWebTokenHandler.ValidateSignature.cs | 20 +++---- ...nWebTokenHandler.ValidateToken.Internal.cs | 6 +-- .../JwtTokenUtilities.DecryptTokenResult.cs | 2 +- .../JwtTokenUtilities.cs | 6 +-- .../TokenUtilities.cs | 28 +++++----- .../Results/Details/ExceptionDetail.cs | 54 +++++++++---------- .../Validation/Validators.Algorithm.cs | 2 +- .../Validation/Validators.Audience.cs | 6 +-- .../Validation/Validators.Issuer.cs | 6 +-- .../Validation/Validators.IssuerSigningKey.cs | 6 +-- .../Validation/Validators.Lifetime.cs | 8 +-- .../Validation/Validators.TokenReplay.cs | 6 +-- .../Validation/Validators.TokenType.cs | 4 +- .../JsonWebTokenHandler.DecryptTokenTests.cs | 8 +-- .../JsonWebTokenHandler.ReadTokenTests.cs | 6 +-- ...nWebTokenHandler.ValidateSignatureTests.cs | 12 ++--- .../AlgorithmValidationResultTests.cs | 4 +- .../AudienceValidationResultTests.cs | 36 ++++++------- .../Validation/ExceptionDetailsTests.cs | 50 ++++++++--------- .../Validation/IssuerValidationResultTests.cs | 8 +-- .../LifetimeValidationResultTests.cs | 14 ++--- .../Validation/ReplayValidationResultTests.cs | 12 ++--- .../SigningKeyValidationResultTests.cs | 12 ++--- .../TokenTypeValidationResultTests.cs | 10 ++-- 26 files changed, 167 insertions(+), 167 deletions(-) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs index 67a1d1f45f..aa864390c3 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs @@ -43,7 +43,7 @@ internal Result DecryptToken( if (string.IsNullOrEmpty(jwtToken.Enc)) return new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10612), - ValidationErrorType.SecurityToken, + ExceptionType.SecurityToken, new StackFrame(true)); (IList? contentEncryptionKeys, ExceptionDetail? exceptionDetail) result = @@ -57,7 +57,7 @@ internal Result DecryptToken( new MessageDetail( TokenLogMessages.IDX10609, LogHelper.MarkAsSecurityArtifact(jwtToken, JwtTokenUtilities.SafeLogJwtToken)), - ValidationErrorType.SecurityTokenDecryptionFailed, + ExceptionType.SecurityTokenDecryptionFailed, new StackFrame(true)); return JwtTokenUtilities.DecryptJwtToken( @@ -195,7 +195,7 @@ internal Result DecryptToken( keysAttempted?.ToString() ?? "", exceptionStrings?.ToString() ?? "", LogHelper.MarkAsSecurityArtifact(jwtToken, JwtTokenUtilities.SafeLogJwtToken)), - ValidationErrorType.SecurityTokenKeyWrap, + ExceptionType.SecurityTokenKeyWrap, new System.Diagnostics.StackFrame(), null); diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs index a98657899d..54c67ca302 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs @@ -43,7 +43,7 @@ internal static Result ReadToken( { return new ExceptionDetail( new MessageDetail(LogMessages.IDX14107), - ValidationErrorType.SecurityTokenMalformed, + ExceptionType.SecurityTokenMalformed, new StackFrame(true), ex); } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs index cd3a342bae..ba92e216d2 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs @@ -61,7 +61,7 @@ internal static Result ValidateSignature( LogHelper.MarkAsSecurityArtifact( jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - ValidationErrorType.SecurityTokenInvalidSignature, + ExceptionType.SecurityTokenInvalidSignature, new StackFrame(true)); SecurityKey? key = null; @@ -99,7 +99,7 @@ internal static Result ValidateSignature( StackFrame stackFrame = SignatureStackFrames.NoKeysProvided ??= new StackFrame(true); return new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10500), - ValidationErrorType.SecurityTokenSignatureKeyNotFound, + ExceptionType.SecurityTokenSignatureKeyNotFound, stackFrame); } } @@ -135,7 +135,7 @@ private static Result ValidateSignatureUsingAllKey if (vpFailedResult is null && configFailedResult is null) // No keys were attempted return new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10500), - ValidationErrorType.SecurityTokenSignatureKeyNotFound, + ExceptionType.SecurityTokenSignatureKeyNotFound, new StackFrame(true)); StringBuilder exceptionStrings = new(); @@ -216,7 +216,7 @@ private static Result ValidateSignatureWithKey( TokenLogMessages.IDX10400, LogHelper.MarkAsNonPII(jsonWebToken.Alg), key), - ValidationErrorType.SecurityTokenInvalidAlgorithm, + ExceptionType.SecurityTokenInvalidAlgorithm, new StackFrame(true)); } @@ -239,7 +239,7 @@ private static Result ValidateSignatureWithKey( TokenLogMessages.IDX10636, key?.ToString() ?? "Null", LogHelper.MarkAsNonPII(jsonWebToken.Alg)), - ValidationErrorType.InvalidOperation, + ExceptionType.InvalidOperation, new StackFrame(true)); bool valid = EncodingUtils.PerformEncodingDependentOperation( @@ -261,7 +261,7 @@ private static Result ValidateSignatureWithKey( LogHelper.MarkAsSecurityArtifact( jsonWebToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - ValidationErrorType.SecurityTokenInvalidSignature, + ExceptionType.SecurityTokenInvalidSignature, new StackFrame(true)); } #pragma warning disable CA1031 // Do not catch general exception types @@ -274,7 +274,7 @@ private static Result ValidateSignatureWithKey( LogHelper.MarkAsSecurityArtifact( jsonWebToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - ValidationErrorType.SecurityTokenInvalidSignature, + ExceptionType.SecurityTokenInvalidSignature, new StackFrame(true), ex); } @@ -314,7 +314,7 @@ private static ExceptionDetail GetSignatureValidationError( LogHelper.MarkAsNonPII(jwtToken.Kid), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - ValidationErrorType.SecurityTokenSignatureKeyNotFound, + ExceptionType.SecurityTokenSignatureKeyNotFound, new StackFrame(true)); } @@ -328,7 +328,7 @@ private static ExceptionDetail GetSignatureValidationError( LogHelper.MarkAsNonPII(numKeysInConfiguration), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - ValidationErrorType.SecurityTokenSignatureKeyNotFound, + ExceptionType.SecurityTokenSignatureKeyNotFound, new StackFrame(true)); return new ExceptionDetail( @@ -339,7 +339,7 @@ private static ExceptionDetail GetSignatureValidationError( LogHelper.MarkAsNonPII(numKeysInConfiguration), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), - ValidationErrorType.SecurityTokenSignatureKeyNotFound, + ExceptionType.SecurityTokenSignatureKeyNotFound, new StackFrame(true)); } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs index 06a4f05666..02bc3a11c7 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs @@ -74,7 +74,7 @@ internal async Task ValidateTokenAsync( TokenLogMessages.IDX10209, LogHelper.MarkAsNonPII(token.Length), LogHelper.MarkAsNonPII(MaximumTokenSizeInBytes)), - ValidationErrorType.InvalidArgument, + ExceptionType.InvalidArgument, new StackFrame(true))); Result result = ReadToken(token, callContext); @@ -126,7 +126,7 @@ internal async Task ValidateTokenAsync( validationParameters, new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10001, nameof(token), nameof(JsonWebToken)), - ValidationErrorType.InvalidArgument, + ExceptionType.InvalidArgument, new StackFrame(true))); return await InternalValidateTokenAsync( @@ -205,7 +205,7 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration, { validationParameters.RefreshBeforeValidation = false; validationParameters.ValidateWithLKG = true; - ValidationErrorType recoverableExceptionType = result.ExceptionDetail?.Type ?? ValidationErrorType.Unknown; + ExceptionType recoverableExceptionType = result.ExceptionDetail?.Type ?? ExceptionType.Unknown; BaseConfiguration[] validConfigurations = validationParameters.ConfigurationManager.GetValidLkgConfigurations(); for (int i = 0; i < validConfigurations.Length; i++) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs index 19334194f1..a8128208ae 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs @@ -124,7 +124,7 @@ internal static Result DecryptJwtToken( { return new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10679, zipAlgorithm), - ValidationErrorType.SecurityTokenDecompressionFailed, + ExceptionType.SecurityTokenDecompressionFailed, new StackFrame(true), ex); } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs index 335dbbd8dc..59231a8652 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs @@ -371,7 +371,7 @@ private static ExceptionDetail GetDecryptionError( keysAttempted.ToString(), exceptionStrings?.ToString() ?? string.Empty, LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken)), - ValidationErrorType.SecurityTokenDecryptionFailed, + ExceptionType.SecurityTokenDecryptionFailed, new StackFrame(true), null); else if (algorithmNotSupportedByCryptoProvider) @@ -380,14 +380,14 @@ private static ExceptionDetail GetDecryptionError( TokenLogMessages.IDX10619, LogHelper.MarkAsNonPII(decryptionParameters.Alg), LogHelper.MarkAsNonPII(decryptionParameters.Enc)), - ValidationErrorType.SecurityTokenDecryptionFailed, + ExceptionType.SecurityTokenDecryptionFailed, new StackFrame(true)); else return new ExceptionDetail( new MessageDetail( TokenLogMessages.IDX10609, LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken)), - ValidationErrorType.SecurityTokenDecryptionFailed, + ExceptionType.SecurityTokenDecryptionFailed, new StackFrame(true)); } diff --git a/src/Microsoft.IdentityModel.Tokens/TokenUtilities.cs b/src/Microsoft.IdentityModel.Tokens/TokenUtilities.cs index b676725f41..5047904a92 100644 --- a/src/Microsoft.IdentityModel.Tokens/TokenUtilities.cs +++ b/src/Microsoft.IdentityModel.Tokens/TokenUtilities.cs @@ -258,13 +258,13 @@ internal static bool IsRecoverableException(Exception exception) /// /// The exception type to check. /// true if the exception is certain types of exceptions otherwise, false. - internal static bool IsRecoverableErrorType(ValidationErrorType? errorType) + internal static bool IsRecoverableErrorType(ExceptionType? errorType) { - ValidationErrorType typeToCheck = errorType ?? ValidationErrorType.Unknown; + ExceptionType typeToCheck = errorType ?? ExceptionType.Unknown; - return typeToCheck == ValidationErrorType.SecurityTokenInvalidSignature - || typeToCheck == ValidationErrorType.SecurityTokenInvalidIssuer - || typeToCheck == ValidationErrorType.SecurityTokenSignatureKeyNotFound; + return typeToCheck == ExceptionType.SecurityTokenInvalidSignature + || typeToCheck == ExceptionType.SecurityTokenInvalidIssuer + || typeToCheck == ExceptionType.SecurityTokenSignatureKeyNotFound; } /// @@ -291,19 +291,19 @@ internal static bool IsRecoverableConfiguration( /// The exception type to check. /// true if the configuration is recoverable otherwise, false. internal static bool IsRecoverableConfigurationAndExceptionType( - string kid, BaseConfiguration currentConfiguration, BaseConfiguration lkgConfiguration, ValidationErrorType currentExceptionType) + string kid, BaseConfiguration currentConfiguration, BaseConfiguration lkgConfiguration, ExceptionType currentExceptionType) { Lazy isRecoverableSigningKey = new(() => lkgConfiguration.SigningKeys.Any(signingKey => signingKey.KeyId == kid)); - if (currentExceptionType == ValidationErrorType.SecurityTokenInvalidIssuer) + if (currentExceptionType == ExceptionType.SecurityTokenInvalidIssuer) { return currentConfiguration.Issuer != lkgConfiguration.Issuer; } - else if (currentExceptionType == ValidationErrorType.SecurityTokenSignatureKeyNotFound) + else if (currentExceptionType == ExceptionType.SecurityTokenSignatureKeyNotFound) { return isRecoverableSigningKey.Value; } - else if (currentExceptionType == ValidationErrorType.SecurityTokenInvalidSignature) + else if (currentExceptionType == ExceptionType.SecurityTokenInvalidSignature) { SecurityKey currentSigningKey = currentConfiguration.SigningKeys.FirstOrDefault(x => x.KeyId == kid); if (currentSigningKey == null) @@ -316,16 +316,16 @@ internal static bool IsRecoverableConfigurationAndExceptionType( return false; } - static ValidationErrorType ErrorTypeForException(Exception exception) + static ExceptionType ErrorTypeForException(Exception exception) { if (exception is SecurityTokenInvalidSignatureException) - return ValidationErrorType.SecurityTokenInvalidSignature; + return ExceptionType.SecurityTokenInvalidSignature; else if (exception is SecurityTokenInvalidIssuerException) - return ValidationErrorType.SecurityTokenInvalidIssuer; + return ExceptionType.SecurityTokenInvalidIssuer; else if (exception is SecurityTokenSignatureKeyNotFoundException) - return ValidationErrorType.SecurityTokenSignatureKeyNotFound; + return ExceptionType.SecurityTokenSignatureKeyNotFound; else - return ValidationErrorType.Unknown; + return ExceptionType.Unknown; } } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs index b9ff348217..62b2197c13 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs @@ -18,7 +18,7 @@ internal class ExceptionDetail /// contains information about the exception that is used to generate the exception message. /// is the type of exception that occurred. /// is the stack frame where the exception occurred. - public ExceptionDetail(MessageDetail messageDetail, ValidationErrorType exceptionType, StackFrame stackFrame) + public ExceptionDetail(MessageDetail messageDetail, ExceptionType exceptionType, StackFrame stackFrame) : this(messageDetail, exceptionType, stackFrame, null) { } @@ -30,7 +30,7 @@ public ExceptionDetail(MessageDetail messageDetail, ValidationErrorType exceptio /// is the type of exception that occurred. /// is the stack frame where the exception occurred. /// is the inner exception that occurred. - public ExceptionDetail(MessageDetail messageDetail, ValidationErrorType exceptionType, StackFrame stackFrame, Exception innerException) + public ExceptionDetail(MessageDetail messageDetail, ExceptionType exceptionType, StackFrame stackFrame, Exception innerException) { Type = exceptionType; InnerException = innerException; @@ -56,12 +56,12 @@ public Exception GetException() internal static ExceptionDetail NullParameter(string parameterName, StackFrame stackFrame) => new ExceptionDetail( MessageDetail.NullParameter(parameterName), - ValidationErrorType.ArgumentNull, stackFrame); + ExceptionType.ArgumentNull, stackFrame); /// /// Gets the type of exception that occurred. /// - public ValidationErrorType Type { get; } + public ExceptionType Type { get; } /// /// Gets the inner exception that occurred. @@ -79,53 +79,53 @@ public Exception GetException() public IList StackFrames { get; } public static Exception ExceptionFromType( - ValidationErrorType exceptionType, + ExceptionType exceptionType, MessageDetail messageDetail, Exception innerException) { switch (exceptionType) { - case ValidationErrorType.ArgumentNull: + case ExceptionType.ArgumentNull: return new ArgumentNullException(messageDetail.Message, innerException); - case ValidationErrorType.InvalidArgument: + case ExceptionType.InvalidArgument: return new ArgumentException(messageDetail.Message, innerException); - case ValidationErrorType.InvalidOperation: + case ExceptionType.InvalidOperation: return new InvalidOperationException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityToken: + case ExceptionType.SecurityToken: return new SecurityTokenException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenDecompressionFailed: + case ExceptionType.SecurityTokenDecompressionFailed: return new SecurityTokenDecompressionFailedException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenDecryptionFailed: + case ExceptionType.SecurityTokenDecryptionFailed: return new SecurityTokenDecryptionFailedException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenExpired: + case ExceptionType.SecurityTokenExpired: return new SecurityTokenExpiredException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenInvalidAudience: + case ExceptionType.SecurityTokenInvalidAudience: return new SecurityTokenInvalidAudienceException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenInvalidAlgorithm: + case ExceptionType.SecurityTokenInvalidAlgorithm: return new SecurityTokenInvalidAlgorithmException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenInvalidIssuer: + case ExceptionType.SecurityTokenInvalidIssuer: return new SecurityTokenInvalidIssuerException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenInvalidLifetime: + case ExceptionType.SecurityTokenInvalidLifetime: return new SecurityTokenInvalidLifetimeException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenInvalidSignature: + case ExceptionType.SecurityTokenInvalidSignature: return new SecurityTokenInvalidSignatureException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenInvalidSigningKey: + case ExceptionType.SecurityTokenInvalidSigningKey: return new SecurityTokenInvalidSigningKeyException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenInvalidType: + case ExceptionType.SecurityTokenInvalidType: return new SecurityTokenInvalidTypeException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenKeyWrap: + case ExceptionType.SecurityTokenKeyWrap: return new SecurityTokenKeyWrapException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenMalformed: + case ExceptionType.SecurityTokenMalformed: return new SecurityTokenMalformedException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenNoExpiration: + case ExceptionType.SecurityTokenNoExpiration: return new SecurityTokenNoExpirationException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenNotYetValid: + case ExceptionType.SecurityTokenNotYetValid: return new SecurityTokenNotYetValidException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenReplayDetected: + case ExceptionType.SecurityTokenReplayDetected: return new SecurityTokenReplayDetectedException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenReplayAddFailed: + case ExceptionType.SecurityTokenReplayAddFailed: return new SecurityTokenReplayAddFailedException(messageDetail.Message, innerException); - case ValidationErrorType.SecurityTokenSignatureKeyNotFound: + case ExceptionType.SecurityTokenSignatureKeyNotFound: return new SecurityTokenSignatureKeyNotFoundException(messageDetail.Message, innerException); default: throw new ArgumentException("Invalid ExceptionType."); @@ -133,7 +133,7 @@ public static Exception ExceptionFromType( } } - internal enum ValidationErrorType + internal enum ExceptionType { Unknown = -1, ArgumentNull, diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs index a3c4cbc006..c32fc4a2f1 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs @@ -58,7 +58,7 @@ internal static Result ValidateAlgorithm( new MessageDetail( LogMessages.IDX10696, LogHelper.MarkAsNonPII(algorithm)), - ValidationErrorType.SecurityTokenInvalidAlgorithm, + ExceptionType.SecurityTokenInvalidAlgorithm, new StackFrame(true)); return algorithm; diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs index df57362fe8..e193cacc64 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs @@ -54,13 +54,13 @@ internal static Result ValidateAudience(IList t if (tokenAudiences == null) return new ExceptionDetail( new MessageDetail(LogMessages.IDX10207), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, new StackFrame(true)); if (tokenAudiences.Count == 0) return new ExceptionDetail( new MessageDetail(LogMessages.IDX10206), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, new StackFrame(true)); string? validAudience = ValidTokenAudience(tokenAudiences, validationParameters.ValidAudiences, validationParameters.IgnoreTrailingSlashWhenValidatingAudience); @@ -72,7 +72,7 @@ internal static Result ValidateAudience(IList t LogMessages.IDX10215, LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(tokenAudiences)), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidAudiences))), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, new StackFrame(true)); } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs index e3cbd9fcbe..91c6852003 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs @@ -66,7 +66,7 @@ internal static async Task> ValidateIss { return new ExceptionDetail( new MessageDetail(LogMessages.IDX10211), - ValidationErrorType.SecurityTokenInvalidIssuer, + ExceptionType.SecurityTokenInvalidIssuer, new StackFrame(true)); } @@ -88,7 +88,7 @@ internal static async Task> ValidateIss if (validationParameters.ValidIssuers.Count == 0 && string.IsNullOrWhiteSpace(configuration?.Issuer)) return new ExceptionDetail( new MessageDetail(LogMessages.IDX10211), - ValidationErrorType.SecurityTokenInvalidIssuer, + ExceptionType.SecurityTokenInvalidIssuer, new StackFrame(true)); if (configuration != null) @@ -137,7 +137,7 @@ internal static async Task> ValidateIss LogHelper.MarkAsNonPII(issuer), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidIssuers)), LogHelper.MarkAsNonPII(configuration?.Issuer)), - ValidationErrorType.SecurityTokenInvalidIssuer, + ExceptionType.SecurityTokenInvalidIssuer, new StackFrame(true)); } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs index 389633fe7a..025aaa4f8e 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs @@ -63,7 +63,7 @@ internal static Result ValidateIss if (securityKey == null) return new ExceptionDetail( new MessageDetail(LogMessages.IDX10253, nameof(securityKey)), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, new StackFrame(true)); if (securityToken == null) @@ -103,7 +103,7 @@ internal static Result ValidateIss LogMessages.IDX10248, LogHelper.MarkAsNonPII(notBeforeUtc), LogHelper.MarkAsNonPII(utcNow)), - ValidationErrorType.SecurityTokenInvalidSigningKey, + ExceptionType.SecurityTokenInvalidSigningKey, new StackFrame(true)); //TODO: Move to CallContext @@ -116,7 +116,7 @@ internal static Result ValidateIss LogMessages.IDX10249, LogHelper.MarkAsNonPII(notAfterUtc), LogHelper.MarkAsNonPII(utcNow)), - ValidationErrorType.SecurityTokenInvalidSigningKey, + ExceptionType.SecurityTokenInvalidSigningKey, new StackFrame(true)); // TODO: Move to CallContext diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs index 4f3c8d84fe..ccb13f468d 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs @@ -67,7 +67,7 @@ internal static Result ValidateLifetime( new MessageDetail( LogMessages.IDX10225, LogHelper.MarkAsNonPII(securityToken == null ? "null" : securityToken.GetType().ToString())), - ValidationErrorType.SecurityTokenNoExpiration, + ExceptionType.SecurityTokenNoExpiration, new StackFrame(true)); if (notBefore.HasValue && expires.HasValue && (notBefore.Value > expires.Value)) @@ -76,7 +76,7 @@ internal static Result ValidateLifetime( LogMessages.IDX10224, LogHelper.MarkAsNonPII(notBefore.Value), LogHelper.MarkAsNonPII(expires.Value)), - ValidationErrorType.SecurityTokenInvalidLifetime, + ExceptionType.SecurityTokenInvalidLifetime, new StackFrame(true)); DateTime utcNow = DateTime.UtcNow; @@ -86,7 +86,7 @@ internal static Result ValidateLifetime( LogMessages.IDX10222, LogHelper.MarkAsNonPII(notBefore.Value), LogHelper.MarkAsNonPII(utcNow)), - ValidationErrorType.SecurityTokenNotYetValid, + ExceptionType.SecurityTokenNotYetValid, new StackFrame(true)); if (expires.HasValue && (expires.Value < DateTimeUtil.Add(utcNow, validationParameters.ClockSkew.Negate()))) @@ -95,7 +95,7 @@ internal static Result ValidateLifetime( LogMessages.IDX10223, LogHelper.MarkAsNonPII(expires.Value), LogHelper.MarkAsNonPII(utcNow)), - ValidationErrorType.SecurityTokenExpired, + ExceptionType.SecurityTokenExpired, new StackFrame(true)); // if it reaches here, that means lifetime of the token is valid diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs index cf416c67a8..c74114e147 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs @@ -62,7 +62,7 @@ public static partial class Validators new MessageDetail( LogMessages.IDX10227, LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), - ValidationErrorType.SecurityTokenReplayDetected, + ExceptionType.SecurityTokenReplayDetected, new StackFrame(true)); if (validationParameters.TokenReplayCache.TryFind(securityToken)) @@ -70,7 +70,7 @@ public static partial class Validators new MessageDetail( LogMessages.IDX10228, LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), - ValidationErrorType.SecurityTokenReplayDetected, + ExceptionType.SecurityTokenReplayDetected, new StackFrame(true)); if (!validationParameters.TokenReplayCache.TryAdd(securityToken, expirationTime.Value)) @@ -78,7 +78,7 @@ public static partial class Validators new MessageDetail( LogMessages.IDX10229, LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), - ValidationErrorType.SecurityTokenReplayAddFailed, + ExceptionType.SecurityTokenReplayAddFailed, new StackFrame(true)); } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs index 1b43466145..bf741ed390 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs @@ -66,7 +66,7 @@ internal static Result ValidateTokenType( if (string.IsNullOrEmpty(type)) return new ExceptionDetail( new MessageDetail(LogMessages.IDX10256), - ValidationErrorType.SecurityTokenInvalidType, + ExceptionType.SecurityTokenInvalidType, new StackFrame(true)); if (!validationParameters.ValidTypes.Contains(type, StringComparer.Ordinal)) @@ -76,7 +76,7 @@ internal static Result ValidateTokenType( LogMessages.IDX10257, LogHelper.MarkAsNonPII(type), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidTypes))), - ValidationErrorType.SecurityTokenInvalidType, + ExceptionType.SecurityTokenInvalidType, new StackFrame(true)); } diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.DecryptTokenTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.DecryptTokenTests.cs index 21846efd78..f472508937 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.DecryptTokenTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.DecryptTokenTests.cs @@ -104,7 +104,7 @@ public static TheoryData JsonWebTokenHandlerDecryptTo ExpectedException = ExpectedException.SecurityTokenException("IDX10612:"), Result = new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10612), - ValidationErrorType.SecurityToken, + ExceptionType.SecurityToken, null, null), }, @@ -116,7 +116,7 @@ public static TheoryData JsonWebTokenHandlerDecryptTo ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), Result = new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10000, "jwtToken"), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null), }, @@ -128,7 +128,7 @@ public static TheoryData JsonWebTokenHandlerDecryptTo ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), Result = new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10000, "validationParameters"), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null), }, @@ -185,7 +185,7 @@ public static TheoryData JsonWebTokenHandlerDecryptTo LogHelper.MarkAsSecurityArtifact( new JsonWebToken(ReferenceTokens.JWEDirectEncryptionUnsignedInnerJWTWithAdditionalHeaderClaims), JwtTokenUtilities.SafeLogJwtToken)), - ValidationErrorType.SecurityTokenDecryptionFailed, + ExceptionType.SecurityTokenDecryptionFailed, null, null), } diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs index 477985885b..30cf258f1f 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs @@ -71,7 +71,7 @@ public static TheoryData JsonWebTokenHandlerReadTokenTes new MessageDetail( TokenLogMessages.IDX10000, LogHelper.MarkAsNonPII("token")), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null) }, @@ -84,7 +84,7 @@ public static TheoryData JsonWebTokenHandlerReadTokenTes new MessageDetail( TokenLogMessages.IDX10000, LogHelper.MarkAsNonPII("token")), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null) }, @@ -99,7 +99,7 @@ public static TheoryData JsonWebTokenHandlerReadTokenTes new MessageDetail( LogMessages.IDX14107, LogHelper.MarkAsNonPII("token")), - ValidationErrorType.SecurityTokenMalformed, + ExceptionType.SecurityTokenMalformed, null, new SecurityTokenMalformedException()), } diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs index bf803e9a25..8a0593daf8 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs @@ -81,7 +81,7 @@ public static TheoryData JsonWeb new MessageDetail( TokenLogMessages.IDX10000, "jwtToken"), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null) }, @@ -94,7 +94,7 @@ public static TheoryData JsonWeb new MessageDetail( TokenLogMessages.IDX10000, "validationParameters"), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null) }, @@ -110,7 +110,7 @@ public static TheoryData JsonWeb new MessageDetail( TokenLogMessages.IDX10000, "fakeParameter"), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null) }, @@ -124,7 +124,7 @@ public static TheoryData JsonWeb new MessageDetail( TokenLogMessages.IDX10504, LogHelper.MarkAsSecurityArtifact(unsignedToken, JwtTokenUtilities.SafeLogJwtToken)), - ValidationErrorType.SecurityTokenInvalidSignature, + ExceptionType.SecurityTokenInvalidSignature, null, null) }, @@ -193,7 +193,7 @@ public static TheoryData JsonWeb ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException("IDX10500:"), Result = new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10500), - ValidationErrorType.SecurityTokenSignatureKeyNotFound, + ExceptionType.SecurityTokenSignatureKeyNotFound, null, null) }, @@ -205,7 +205,7 @@ public static TheoryData JsonWeb ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException("IDX10500:"), Result = new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10500), - ValidationErrorType.SecurityTokenSignatureKeyNotFound, + ExceptionType.SecurityTokenSignatureKeyNotFound, null, null) } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs index ca931e3b3f..8d42a4b39a 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs @@ -61,7 +61,7 @@ public static TheoryData AlgorithmValidationTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, // StackFrame null) // InnerException }, @@ -80,7 +80,7 @@ public static TheoryData AlgorithmValidationTestCases new MessageDetail( LogMessages.IDX10696, LogHelper.MarkAsNonPII(SecurityAlgorithms.Sha256)), - ValidationErrorType.SecurityTokenInvalidAlgorithm, + ExceptionType.SecurityTokenInvalidAlgorithm, null, // StackFrame null),// InnerException }, diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs index c3026d8182..fa8c197805 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs @@ -80,7 +80,7 @@ public static TheoryData ValidateAudienceTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null) }, @@ -91,7 +91,7 @@ public static TheoryData ValidateAudienceTestCases ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10207:"), Result = new ExceptionDetail( new MessageDetail(LogMessages.IDX10207), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null, null) }, @@ -105,7 +105,7 @@ public static TheoryData ValidateAudienceTestCases new MessageDetail( LogMessages.IDX10206, null), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null, null) }, @@ -121,7 +121,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII("audience1"), LogHelper.MarkAsNonPII(String.Empty)), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null, null) }, @@ -137,7 +137,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII("audience1"), LogHelper.MarkAsNonPII(" ")), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null, null) }, @@ -163,7 +163,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience2)), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null, null) }, @@ -180,7 +180,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience2Slash)), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null, null) }, @@ -196,7 +196,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience2Slash), LogHelper.MarkAsNonPII(audience1)), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null, null) }, @@ -212,7 +212,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience1Slash)), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null) }, new AudienceValidationTheoryData @@ -235,7 +235,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(commaAudience1Slash)), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null, null) }, @@ -259,7 +259,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience1 + "A")), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null, null) }, @@ -275,7 +275,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience1 + "//")), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null, null) }, @@ -291,7 +291,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(commaAudience1 + "//")), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null, null) }, @@ -307,7 +307,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1Slash), LogHelper.MarkAsNonPII(audience1)), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null, null) }, @@ -331,7 +331,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience2Slash), LogHelper.MarkAsNonPII(audience1)), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null, null) }, @@ -347,7 +347,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1Slash), LogHelper.MarkAsNonPII(audience1)), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null, null) }, @@ -371,7 +371,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1Slash), LogHelper.MarkAsNonPII(commaAudience2)), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null, null) }, @@ -387,7 +387,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1 + "//"), LogHelper.MarkAsNonPII(audience1)), - ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType.SecurityTokenInvalidAudience, null, null) } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ExceptionDetailsTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ExceptionDetailsTests.cs index ac77b5b632..de7bb505d6 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ExceptionDetailsTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ExceptionDetailsTests.cs @@ -30,7 +30,7 @@ public void ExceptionDetails_UnknownType_Throws() { ExceptionDetail exceptionDetail = new ExceptionDetail( new MessageDetail(""), - ValidationErrorType.Unknown, + ExceptionType.Unknown, null); Assert.Throws(() => exceptionDetail.GetException()); @@ -39,8 +39,8 @@ public void ExceptionDetails_UnknownType_Throws() [Fact] public void All_ExceptionDetails_HaveTests() { - // If this test fails, we are missing a test for a new ValidationErrorType - Assert.Equal(((int)ValidationErrorType.ExceptionTypeCount), ExceptionDetailsTestCases.Count()); + // If this test fails, we are missing a test for a new ExceptionType + Assert.Equal(((int)ExceptionType.ExceptionTypeCount), ExceptionDetailsTestCases.Count()); } public static TheoryData ExceptionDetailsTestCases @@ -52,127 +52,127 @@ public static TheoryData ExceptionDetailsTestCases new ExceptionDetailsTheoryData { TestId = "ArgumentNull", - ExceptionType = ValidationErrorType.ArgumentNull, + ExceptionType = ExceptionType.ArgumentNull, ExpectedException = ExpectedException.ArgumentNullException(), }, new ExceptionDetailsTheoryData { TestId = "InvalidArgument", - ExceptionType = ValidationErrorType.InvalidArgument, + ExceptionType = ExceptionType.InvalidArgument, ExpectedException = ExpectedException.ArgumentException(), }, new ExceptionDetailsTheoryData { TestId = "InvalidOperation", - ExceptionType = ValidationErrorType.InvalidOperation, + ExceptionType = ExceptionType.InvalidOperation, ExpectedException = ExpectedException.InvalidOperationException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityToken", - ExceptionType = ValidationErrorType.SecurityToken, + ExceptionType = ExceptionType.SecurityToken, ExpectedException = ExpectedException.SecurityTokenException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenDecompressionFailed", - ExceptionType = ValidationErrorType.SecurityTokenDecompressionFailed, + ExceptionType = ExceptionType.SecurityTokenDecompressionFailed, ExpectedException = ExpectedException.SecurityTokenDecompressionFailedException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenDecryptionFailed", - ExceptionType = ValidationErrorType.SecurityTokenDecryptionFailed, + ExceptionType = ExceptionType.SecurityTokenDecryptionFailed, ExpectedException = ExpectedException.SecurityTokenDecryptionFailedException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenExpired", - ExceptionType = ValidationErrorType.SecurityTokenExpired, + ExceptionType = ExceptionType.SecurityTokenExpired, ExpectedException = ExpectedException.SecurityTokenExpiredException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenInvalidAudience", - ExceptionType = ValidationErrorType.SecurityTokenInvalidAudience, + ExceptionType = ExceptionType.SecurityTokenInvalidAudience, ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenInvalidAlgorithm", - ExceptionType = ValidationErrorType.SecurityTokenInvalidAlgorithm, + ExceptionType = ExceptionType.SecurityTokenInvalidAlgorithm, ExpectedException = ExpectedException.SecurityTokenInvalidAlgorithmException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenInvalidIssuer", - ExceptionType = ValidationErrorType.SecurityTokenInvalidIssuer, + ExceptionType = ExceptionType.SecurityTokenInvalidIssuer, ExpectedException = ExpectedException.SecurityTokenInvalidIssuerException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenInvalidLifetime", - ExceptionType = ValidationErrorType.SecurityTokenInvalidLifetime, + ExceptionType = ExceptionType.SecurityTokenInvalidLifetime, ExpectedException = ExpectedException.SecurityTokenInvalidLifetimeException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenInvalidSigningKey", - ExceptionType = ValidationErrorType.SecurityTokenInvalidSigningKey, + ExceptionType = ExceptionType.SecurityTokenInvalidSigningKey, ExpectedException = ExpectedException.SecurityTokenInvalidSigningKeyException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenInvalidSignature", - ExceptionType = ValidationErrorType.SecurityTokenInvalidSignature, + ExceptionType = ExceptionType.SecurityTokenInvalidSignature, ExpectedException = ExpectedException.SecurityTokenInvalidSignatureException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenInvalidType", - ExceptionType = ValidationErrorType.SecurityTokenInvalidType, + ExceptionType = ExceptionType.SecurityTokenInvalidType, ExpectedException = ExpectedException.SecurityTokenInvalidTypeException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenKeyWrap", - ExceptionType = ValidationErrorType.SecurityTokenKeyWrap, + ExceptionType = ExceptionType.SecurityTokenKeyWrap, ExpectedException = ExpectedException.SecurityTokenKeyWrapException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenMalformed", - ExceptionType = ValidationErrorType.SecurityTokenMalformed, + ExceptionType = ExceptionType.SecurityTokenMalformed, ExpectedException = ExpectedException.SecurityTokenMalformedException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenNoExpiration", - ExceptionType = ValidationErrorType.SecurityTokenNoExpiration, + ExceptionType = ExceptionType.SecurityTokenNoExpiration, ExpectedException = ExpectedException.SecurityTokenNoExpirationException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenNotYetValid", - ExceptionType = ValidationErrorType.SecurityTokenNotYetValid, + ExceptionType = ExceptionType.SecurityTokenNotYetValid, ExpectedException = ExpectedException.SecurityTokenNotYetValidException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenReplayDetected", - ExceptionType = ValidationErrorType.SecurityTokenReplayDetected, + ExceptionType = ExceptionType.SecurityTokenReplayDetected, ExpectedException = ExpectedException.SecurityTokenReplayDetectedException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenReplayAddFailed", - ExceptionType = ValidationErrorType.SecurityTokenReplayAddFailed, + ExceptionType = ExceptionType.SecurityTokenReplayAddFailed, ExpectedException = ExpectedException.SecurityTokenReplayAddFailedException(), }, new ExceptionDetailsTheoryData { TestId = "SecurityTokenSignatureKeyNotFound", - ExceptionType = ValidationErrorType.SecurityTokenSignatureKeyNotFound, + ExceptionType = ExceptionType.SecurityTokenSignatureKeyNotFound, ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException(), }, }; @@ -182,6 +182,6 @@ public static TheoryData ExceptionDetailsTestCases public class ExceptionDetailsTheoryData : TheoryDataBase { - internal ValidationErrorType ExceptionType { get; set; } + internal ExceptionType ExceptionType { get; set; } } } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs index 04210ac377..0eacbeec47 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs @@ -70,7 +70,7 @@ public static TheoryData IssuerValdationResul LogHelper.MarkAsNonPII(validIssuer), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(null)), LogHelper.MarkAsNonPII(null)), - ValidationErrorType.SecurityTokenInvalidIssuer, + ExceptionType.SecurityTokenInvalidIssuer, null, null), SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, issClaim), @@ -85,7 +85,7 @@ public static TheoryData IssuerValdationResul new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null), SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, issClaim), @@ -100,7 +100,7 @@ public static TheoryData IssuerValdationResul new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null), SecurityToken = null, @@ -137,7 +137,7 @@ public static TheoryData IssuerValdationResul LogHelper.MarkAsNonPII(issClaim), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validIssuers)), LogHelper.MarkAsNonPII(null)), - ValidationErrorType.SecurityTokenInvalidIssuer, + ExceptionType.SecurityTokenInvalidIssuer, null, null), SecurityToken = JsonUtilities.CreateUnsignedJsonWebToken(JwtRegisteredClaimNames.Iss, issClaim), diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs index 860c196d75..911f086dca 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs @@ -94,7 +94,7 @@ public static TheoryData ValidateLifetimeTestCases ValidationParameters = null, Result = new ExceptionDetail( new MessageDetail(LogMessages.IDX10000, "validationParameters"), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null), }, @@ -105,7 +105,7 @@ public static TheoryData ValidateLifetimeTestCases ValidationParameters = new ValidationParameters(), Result = new ExceptionDetail( new MessageDetail(LogMessages.IDX10225, "null"), - ValidationErrorType.SecurityTokenNoExpiration, + ExceptionType.SecurityTokenNoExpiration, null, null), }, @@ -120,7 +120,7 @@ public static TheoryData ValidateLifetimeTestCases LogMessages.IDX10224, LogHelper.MarkAsNonPII(oneHourFromNow), LogHelper.MarkAsNonPII(oneHourAgo)), - ValidationErrorType.SecurityTokenInvalidLifetime, + ExceptionType.SecurityTokenInvalidLifetime, null, null), }, @@ -135,7 +135,7 @@ public static TheoryData ValidateLifetimeTestCases LogMessages.IDX10222, LogHelper.MarkAsNonPII(oneHourFromNow), LogHelper.MarkAsNonPII(now)), - ValidationErrorType.SecurityTokenNotYetValid, + ExceptionType.SecurityTokenNotYetValid, null, null), }, @@ -150,7 +150,7 @@ public static TheoryData ValidateLifetimeTestCases LogMessages.IDX10223, LogHelper.MarkAsNonPII(oneHourAgo), LogHelper.MarkAsNonPII(now)), - ValidationErrorType.SecurityTokenExpired, + ExceptionType.SecurityTokenExpired, null, null), }, @@ -165,7 +165,7 @@ public static TheoryData ValidateLifetimeTestCases LogMessages.IDX10222, LogHelper.MarkAsNonPII(sixMinutesFromNow), LogHelper.MarkAsNonPII(now)), - ValidationErrorType.SecurityTokenNotYetValid, + ExceptionType.SecurityTokenNotYetValid, null, null), }, @@ -180,7 +180,7 @@ public static TheoryData ValidateLifetimeTestCases LogMessages.IDX10223, LogHelper.MarkAsNonPII(sixMinutesAgo), LogHelper.MarkAsNonPII(now)), - ValidationErrorType.SecurityTokenExpired, + ExceptionType.SecurityTokenExpired, null), } }; diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs index a2653a131b..7e44d250d8 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs @@ -84,7 +84,7 @@ public static TheoryData TokenReplayValidationTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null), }, @@ -99,7 +99,7 @@ public static TheoryData TokenReplayValidationTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null), }, @@ -114,7 +114,7 @@ public static TheoryData TokenReplayValidationTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null), }, @@ -136,7 +136,7 @@ public static TheoryData TokenReplayValidationTestCases new MessageDetail( LogMessages.IDX10227, LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), - ValidationErrorType.SecurityTokenReplayDetected, + ExceptionType.SecurityTokenReplayDetected, null, null), }, @@ -158,7 +158,7 @@ public static TheoryData TokenReplayValidationTestCases new MessageDetail( LogMessages.IDX10228, LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), - ValidationErrorType.SecurityTokenReplayDetected, + ExceptionType.SecurityTokenReplayDetected, null, null), }, @@ -180,7 +180,7 @@ public static TheoryData TokenReplayValidationTestCases new MessageDetail( LogMessages.IDX10229, LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), - ValidationErrorType.SecurityTokenReplayDetected, + ExceptionType.SecurityTokenReplayDetected, null, null), } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs index f81ee3e04f..fd62fd3653 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs @@ -69,7 +69,7 @@ public static TheoryData SigningKeyValidationTes ValidationParameters = new ValidationParameters(), Result = new ExceptionDetail( new MessageDetail(LogMessages.IDX10253), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null), }, @@ -84,7 +84,7 @@ public static TheoryData SigningKeyValidationTes new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null), }, @@ -99,7 +99,7 @@ public static TheoryData SigningKeyValidationTes new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null), }, @@ -115,7 +115,7 @@ public static TheoryData SigningKeyValidationTes LogMessages.IDX10249, LogHelper.MarkAsNonPII(utcExpired), LogHelper.MarkAsNonPII(utcNow)), - ValidationErrorType.SecurityTokenInvalidSigningKey, + ExceptionType.SecurityTokenInvalidSigningKey, null, null), }, @@ -131,7 +131,7 @@ public static TheoryData SigningKeyValidationTes LogMessages.IDX10248, LogHelper.MarkAsNonPII(utcNotYetValid), LogHelper.MarkAsNonPII(utcNow)), - ValidationErrorType.SecurityTokenInvalidSigningKey, + ExceptionType.SecurityTokenInvalidSigningKey, null, null), }, @@ -144,7 +144,7 @@ public static TheoryData SigningKeyValidationTes ValidationParameters = new ValidationParameters (), Result = new ExceptionDetail( new MessageDetail(LogMessages.IDX10253), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null), }, diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs index 3374f45ddc..a60ff76d9e 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs @@ -79,7 +79,7 @@ public static TheoryData TokenTypeValidationTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null) }, @@ -94,7 +94,7 @@ public static TheoryData TokenTypeValidationTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), - ValidationErrorType.ArgumentNull, + ExceptionType.ArgumentNull, null, null) }, @@ -110,7 +110,7 @@ public static TheoryData TokenTypeValidationTestCases new MessageDetail( LogMessages.IDX10256, LogHelper.MarkAsNonPII("type")), - ValidationErrorType.SecurityTokenInvalidType, + ExceptionType.SecurityTokenInvalidType, null, null) }, @@ -126,7 +126,7 @@ public static TheoryData TokenTypeValidationTestCases new MessageDetail( LogMessages.IDX10256, LogHelper.MarkAsNonPII("type")), - ValidationErrorType.SecurityTokenInvalidType, + ExceptionType.SecurityTokenInvalidType, null, null) }, @@ -143,7 +143,7 @@ public static TheoryData TokenTypeValidationTestCases LogMessages.IDX10257, LogHelper.MarkAsNonPII("type"), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validTypesNoJwt))), - ValidationErrorType.SecurityTokenInvalidType, + ExceptionType.SecurityTokenInvalidType, null, null) } From f932e318d4444e5c071fb6d9ca90e96b1160cfc6 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Sun, 25 Aug 2024 20:39:09 +0100 Subject: [PATCH 21/32] Restored ExceptionFromType method in ExceptionDetail --- .../Results/Details/ExceptionDetail.cs | 55 +++++++++---------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs index 62b2197c13..aa89ff22c1 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs @@ -15,11 +15,11 @@ internal class ExceptionDetail /// /// Creates an instance of /// - /// contains information about the exception that is used to generate the exception message. + /// contains information about the exception that is used to generate the exception message. /// is the type of exception that occurred. /// is the stack frame where the exception occurred. - public ExceptionDetail(MessageDetail messageDetail, ExceptionType exceptionType, StackFrame stackFrame) - : this(messageDetail, exceptionType, stackFrame, null) + public ExceptionDetail(MessageDetail MessageDetail, ExceptionType exceptionType, StackFrame stackFrame) + : this(MessageDetail, exceptionType, stackFrame, null) { } @@ -47,7 +47,7 @@ public ExceptionDetail(MessageDetail messageDetail, ExceptionType exceptionType, /// An instantance of an Exception. public Exception GetException() { - Exception exception = ExceptionFromType(Type, MessageDetail, InnerException); + Exception exception = ExceptionFromType(Type, InnerException); if (exception is SecurityTokenException securityTokenException) securityTokenException.ExceptionDetail = this; @@ -78,55 +78,52 @@ public Exception GetException() /// public IList StackFrames { get; } - public static Exception ExceptionFromType( - ExceptionType exceptionType, - MessageDetail messageDetail, - Exception innerException) + private Exception ExceptionFromType(ExceptionType exceptionType, Exception innerException) { switch (exceptionType) { case ExceptionType.ArgumentNull: - return new ArgumentNullException(messageDetail.Message, innerException); + return new ArgumentNullException(MessageDetail.Message, innerException); case ExceptionType.InvalidArgument: - return new ArgumentException(messageDetail.Message, innerException); + return new ArgumentException(MessageDetail.Message, innerException); case ExceptionType.InvalidOperation: - return new InvalidOperationException(messageDetail.Message, innerException); + return new InvalidOperationException(MessageDetail.Message, innerException); case ExceptionType.SecurityToken: - return new SecurityTokenException(messageDetail.Message, innerException); + return new SecurityTokenException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenDecompressionFailed: - return new SecurityTokenDecompressionFailedException(messageDetail.Message, innerException); + return new SecurityTokenDecompressionFailedException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenDecryptionFailed: - return new SecurityTokenDecryptionFailedException(messageDetail.Message, innerException); + return new SecurityTokenDecryptionFailedException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenExpired: - return new SecurityTokenExpiredException(messageDetail.Message, innerException); + return new SecurityTokenExpiredException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenInvalidAudience: - return new SecurityTokenInvalidAudienceException(messageDetail.Message, innerException); + return new SecurityTokenInvalidAudienceException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenInvalidAlgorithm: - return new SecurityTokenInvalidAlgorithmException(messageDetail.Message, innerException); + return new SecurityTokenInvalidAlgorithmException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenInvalidIssuer: - return new SecurityTokenInvalidIssuerException(messageDetail.Message, innerException); + return new SecurityTokenInvalidIssuerException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenInvalidLifetime: - return new SecurityTokenInvalidLifetimeException(messageDetail.Message, innerException); + return new SecurityTokenInvalidLifetimeException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenInvalidSignature: - return new SecurityTokenInvalidSignatureException(messageDetail.Message, innerException); + return new SecurityTokenInvalidSignatureException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenInvalidSigningKey: - return new SecurityTokenInvalidSigningKeyException(messageDetail.Message, innerException); + return new SecurityTokenInvalidSigningKeyException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenInvalidType: - return new SecurityTokenInvalidTypeException(messageDetail.Message, innerException); + return new SecurityTokenInvalidTypeException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenKeyWrap: - return new SecurityTokenKeyWrapException(messageDetail.Message, innerException); + return new SecurityTokenKeyWrapException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenMalformed: - return new SecurityTokenMalformedException(messageDetail.Message, innerException); + return new SecurityTokenMalformedException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenNoExpiration: - return new SecurityTokenNoExpirationException(messageDetail.Message, innerException); + return new SecurityTokenNoExpirationException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenNotYetValid: - return new SecurityTokenNotYetValidException(messageDetail.Message, innerException); + return new SecurityTokenNotYetValidException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenReplayDetected: - return new SecurityTokenReplayDetectedException(messageDetail.Message, innerException); + return new SecurityTokenReplayDetectedException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenReplayAddFailed: - return new SecurityTokenReplayAddFailedException(messageDetail.Message, innerException); + return new SecurityTokenReplayAddFailedException(MessageDetail.Message, innerException); case ExceptionType.SecurityTokenSignatureKeyNotFound: - return new SecurityTokenSignatureKeyNotFoundException(messageDetail.Message, innerException); + return new SecurityTokenSignatureKeyNotFoundException(MessageDetail.Message, innerException); default: throw new ArgumentException("Invalid ExceptionType."); } From 6d4ac4d4d09f765b16f19bf5c72a8fb91e1cb510 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Mon, 26 Aug 2024 10:48:28 +0100 Subject: [PATCH 22/32] Override Result's empty initialiser and annotate it to prevent wrong initialisation --- src/Microsoft.IdentityModel.Abstractions/Result.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Microsoft.IdentityModel.Abstractions/Result.cs b/src/Microsoft.IdentityModel.Abstractions/Result.cs index 8eeb19d35d..b4fe1f5c6f 100644 --- a/src/Microsoft.IdentityModel.Abstractions/Result.cs +++ b/src/Microsoft.IdentityModel.Abstractions/Result.cs @@ -38,6 +38,14 @@ public Result(TError error) IsSuccess = false; } + /// + /// Empty constructor implementation to prevent creating an empty result. + /// + /// Throws an when called as this should never be used. Always initialize Result with either a value or error. + /// Thrown when called. + [Obsolete("Cannot create an empty result", true)] + public Result() => throw new InvalidOperationException("Cannot create an empty result"); + /// /// Creates a successful result implicitly from the value. /// From 44935be3fd833b57e7f4265e022d2e9ab71ea94a Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Mon, 26 Aug 2024 10:54:08 +0100 Subject: [PATCH 23/32] Removed commented code. --- .../JwtTokenUtilities.DecryptTokenResult.cs | 1 - .../Validation/Validators.Issuer.cs | 2 -- .../Validation/Validators.TokenType.cs | 2 -- 3 files changed, 5 deletions(-) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs index a8128208ae..31f2f51593 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs @@ -5,7 +5,6 @@ using System.Diagnostics; using System.Text; using Microsoft.IdentityModel.Tokens; -//using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Abstractions; using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages; diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs index 91c6852003..437e638736 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs @@ -5,8 +5,6 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.IdentityModel.Abstractions; - -//using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; namespace Microsoft.IdentityModel.Tokens diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs index bf741ed390..579463ccce 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs @@ -5,8 +5,6 @@ using System.Diagnostics; using System.Linq; using Microsoft.IdentityModel.Abstractions; - -//using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; #nullable enable From 7abcffe08aba2373ec9036e8fafc2a307bba7008 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Mon, 26 Aug 2024 11:06:06 +0100 Subject: [PATCH 24/32] Commented empty if statement --- .../JsonWebTokenHandler.DecryptToken.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs index aa864390c3..14d2441956 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs @@ -86,21 +86,22 @@ internal Result DecryptToken( else { var key = ResolveTokenDecryptionKey(jwtToken.EncodedToken, jwtToken, validationParameters, callContext); - if (key != null) - { - // TODO: Move to CallContext - //if (LogHelper.IsEnabled(EventLogLevel.Informational)) - // LogHelper.LogInformation(TokenLogMessages.IDX10904, key); - } - else if (configuration != null) + //if (key is not null) + //{ + // TODO: Move to CallContext or return decryption key source as part of result + //if (LogHelper.IsEnabled(EventLogLevel.Informational)) + // LogHelper.LogInformation(TokenLogMessages.IDX10904, key); + //} + //else + if (key is null && configuration is not null) { key = ResolveTokenDecryptionKeyFromConfig(jwtToken, configuration); - // TODO: Move to CallContext + // TODO: Move to CallContext or return decryption key source as part of result //if (key != null && LogHelper.IsEnabled(EventLogLevel.Informational)) // LogHelper.LogInformation(TokenLogMessages.IDX10905, key); } - if (key != null) + if (key is not null) keys = [key]; } From f18011140b90ca831b3271fc32424f1eb422e147 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Mon, 26 Aug 2024 13:21:54 +0100 Subject: [PATCH 25/32] Added cached stack frames and nullability annotations for ValidateTokenAsync Changed return type to use Result and removed error information from ValidationResult Added method to add StackFrames to ExceptionDetail --- .../ValidateTokenAsyncTests.cs | 17 +- .../JsonWebTokenHandler.DecryptToken.cs | 4 +- ...nWebTokenHandler.ValidateToken.Internal.cs | 331 ++++++++---------- ...bTokenHandler.ValidateToken.StackFrames.cs | 45 +++ .../Results/Details/ExceptionDetail.cs | 11 + .../Validation/Results/ValidationResult.cs | 45 +-- 6 files changed, 216 insertions(+), 237 deletions(-) create mode 100644 src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.StackFrames.cs diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncTests.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncTests.cs index d2659e3b1c..aa366e4019 100644 --- a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncTests.cs +++ b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncTests.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; +using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; @@ -104,8 +105,8 @@ public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP() { // Because ValidationResult is an internal type, we cannot return it in the benchmark. // We return a boolean instead until the type is made public. - ValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - return result.IsValid; + Result result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + return result.IsSuccess; } [BenchmarkCategory("ValidateTokenAsync_FailTwiceBeforeSuccess"), Benchmark(Baseline = true)] @@ -131,11 +132,11 @@ public async Task JsonWebTokenHandler_ValidateTokenAsyncW [BenchmarkCategory("ValidateTokenAsync_FailTwiceBeforeSuccess"), Benchmark] public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP_SucceedOnThirdAttempt() { - ValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + Result result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - return result.IsValid; + return result.IsSuccess; } [BenchmarkCategory("ValidateTokenAsync_FailFourTimesBeforeSuccess"), Benchmark(Baseline = true)] @@ -165,13 +166,13 @@ public async Task JsonWebTokenHandler_ValidateTokenAsyncW [BenchmarkCategory("ValidateTokenAsync_FailFourTimesBeforeSuccess"), Benchmark] public async Task JsonWebTokenHandler_ValidateTokenAsyncWithVP_SucceedOnFifthAttempt() { - ValidationResult result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + Result result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _invalidValidationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - return result.IsValid; + return result.IsSuccess; } [BenchmarkCategory("ValidateTokenAsyncClaimAccess"), Benchmark(Baseline = true)] @@ -186,8 +187,8 @@ public async Task> JsonWebTokenHandler_ValidateTokenAsyncWithTVP_Cre [BenchmarkCategory("ValidateTokenAsyncClaimAccess"), Benchmark] public async Task> JsonWebTokenHandler_ValidateTokenAsyncWithVP_CreateClaims() { - var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); - var claimsIdentity = result.ClaimsIdentity; + Result result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsExtendedClaims, _validationParameters, _callContext, CancellationToken.None).ConfigureAwait(false); + var claimsIdentity = result.UnwrapResult().ClaimsIdentity; var claims = claimsIdentity.Claims; return claims.ToList(); } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs index 14d2441956..99572fcfd1 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs @@ -27,7 +27,7 @@ public partial class JsonWebTokenHandler : TokenHandler internal Result DecryptToken( JsonWebToken jwtToken, ValidationParameters validationParameters, - BaseConfiguration configuration, + BaseConfiguration? configuration, CallContext? callContext) { if (jwtToken == null) @@ -72,7 +72,7 @@ internal Result DecryptToken( callContext); } - internal (IList?, ExceptionDetail?) GetContentEncryptionKeys(JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration configuration, CallContext? callContext) + internal (IList?, ExceptionDetail?) GetContentEncryptionKeys(JsonWebToken jwtToken, ValidationParameters validationParameters, BaseConfiguration? configuration, CallContext? callContext) { IList? keys = null; diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs index 02bc3a11c7..2d412fdcd8 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs @@ -12,15 +12,11 @@ using Microsoft.IdentityModel.Logging; using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages; +#nullable enable namespace Microsoft.IdentityModel.JsonWebTokens { public partial class JsonWebTokenHandler : TokenHandler { - internal static class StackFrames - { - // Test StackFrame to validate caching solution. Need to add all the possible stack frames. - internal static StackFrame SignatureValidationFailed; - } /// /// Validates a token. /// On a validation failure, no exception will be thrown; instead, the exception will be set in the returned TokenValidationResult.Exception property. @@ -30,16 +26,16 @@ internal static class StackFrames /// The to be used for validating the token. /// A that contains useful information for logging. /// A that can be used to request cancellation of the asynchronous operation. - /// A . + /// A with either a if the token was validated or an with the failure information and exception otherwise. /// - /// TokenValidationResult.Exception will be set to one of the following exceptions if the is invalid. + /// ExceptionDetail.GetException() will return one of the following exceptions if the is invalid. /// /// Returned if is null or empty. /// Returned if is null. /// Returned if 'token.Length' is greater than . /// Returned if is not a valid , /// Returned if the validationParameters.TokenReader delegate is not able to parse/read the token as a valid , - internal async Task ValidateTokenAsync( + internal async Task> ValidateTokenAsync( string token, ValidationParameters validationParameters, CallContext callContext, @@ -47,124 +43,104 @@ internal async Task ValidateTokenAsync( { // These exceptions will be removed once we add ExceptionDetails to TokenValidationResult. if (string.IsNullOrEmpty(token)) - return new ValidationResult( - null, - this, - validationParameters, - ExceptionDetail.NullParameter( + { + StackFrame nullTokenStackFrame = StackFrames.TokenStringNull ??= new StackFrame(true); + return ExceptionDetail.NullParameter( nameof(token), - new StackFrame(true))); + nullTokenStackFrame); + } if (validationParameters is null) - return new ValidationResult( - null, - this, - validationParameters, - ExceptionDetail.NullParameter( + { + StackFrame nullValidationParametersStackFrame = StackFrames.TokenStringValidationParametersNull ??= new StackFrame(true); + return ExceptionDetail.NullParameter( nameof(validationParameters), - new StackFrame(true))); + nullValidationParametersStackFrame); + } if (token.Length > MaximumTokenSizeInBytes) - return new ValidationResult( - null, - this, - validationParameters, - new ExceptionDetail( + { + StackFrame invalidTokenLengthStackFrame = StackFrames.InvalidTokenLength ??= new StackFrame(true); + return new ExceptionDetail( new MessageDetail( TokenLogMessages.IDX10209, LogHelper.MarkAsNonPII(token.Length), LogHelper.MarkAsNonPII(MaximumTokenSizeInBytes)), ExceptionType.InvalidArgument, - new StackFrame(true))); + invalidTokenLengthStackFrame); + } - Result result = ReadToken(token, callContext); - if (result.IsSuccess) - return await ValidateTokenAsync( - result.UnwrapResult(), + Result readResult = ReadToken(token, callContext); + if (readResult.IsSuccess) + { + Result validationResult = await ValidateTokenAsync( + readResult.UnwrapResult(), validationParameters, callContext, cancellationToken) .ConfigureAwait(false); - return new ValidationResult( - null, - this, - validationParameters, - result.UnwrapError(), - new StackFrame(true)); + if (validationResult.IsSuccess) + return validationResult; // No need to unwrap and re-wrap the result. + + StackFrame validationFailureStackFrame = StackFrames.TokenStringValidationFailed ??= new StackFrame(true); + return validationResult.UnwrapError().AddStackFrame(validationFailureStackFrame); + } + + StackFrame readFailureStackFrame = StackFrames.TokenStringReadFailed ??= new StackFrame(true); + return readResult.UnwrapError().AddStackFrame(readFailureStackFrame); } /// - internal async Task ValidateTokenAsync( + internal async Task> ValidateTokenAsync( SecurityToken token, ValidationParameters validationParameters, CallContext callContext, CancellationToken cancellationToken) { if (token is null) - return new ValidationResult( - token, - this, - validationParameters, - ExceptionDetail.NullParameter( - nameof(token), - new StackFrame(true))); + { + StackFrame nullTokenStackFrame = StackFrames.TokenNull ??= new StackFrame(true); + return ExceptionDetail.NullParameter( + nameof(token), + nullTokenStackFrame); + } if (validationParameters is null) - return new ValidationResult( - token, - this, - validationParameters, - ExceptionDetail.NullParameter( - nameof(validationParameters), - new StackFrame(true))); - - if (token is not JsonWebToken jwt) - return new ValidationResult( - token, - this, - validationParameters, - new ExceptionDetail( - new MessageDetail(TokenLogMessages.IDX10001, nameof(token), nameof(JsonWebToken)), - ExceptionType.InvalidArgument, - new StackFrame(true))); + { + StackFrame nullValidationParametersStackFrame = StackFrames.TokenValidationParametersNull ??= new StackFrame(true); + return ExceptionDetail.NullParameter( + nameof(validationParameters), + nullValidationParametersStackFrame); + } - return await InternalValidateTokenAsync( - jwt, - validationParameters, - callContext, - cancellationToken) - .ConfigureAwait(false); - } + if (token is not JsonWebToken jsonWebToken) + { + StackFrame notJwtStackFrame = StackFrames.TokenNotJWT ??= new StackFrame(true); + return new ExceptionDetail( + new MessageDetail(TokenLogMessages.IDX10001, nameof(token), nameof(JsonWebToken)), + ExceptionType.InvalidArgument, + notJwtStackFrame); + } - /// - /// Internal method for token validation, responsible for: - /// (1) Obtaining a configuration from the . - /// (2) Revalidating using the Last Known Good Configuration (if present), and obtaining a refreshed configuration (if necessary) and revalidating using it. - /// - /// The JWT token. - /// The to be used for validating the token. - /// A that contains useful information for logging. - /// A that can be used to request cancellation of the asynchronous operation. - /// - private async ValueTask InternalValidateTokenAsync( - JsonWebToken jsonWebToken, - ValidationParameters validationParameters, - CallContext callContext, - CancellationToken cancellationToken) - { - BaseConfiguration currentConfiguration = + BaseConfiguration? currentConfiguration = await GetCurrentConfigurationAsync(validationParameters) .ConfigureAwait(false); - ValidationResult result = jsonWebToken.IsEncrypted ? + Result result = jsonWebToken.IsEncrypted ? await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration, callContext, cancellationToken).ConfigureAwait(false) : await ValidateJWSAsync(jsonWebToken, validationParameters, currentConfiguration, callContext, cancellationToken).ConfigureAwait(false); if (validationParameters.ConfigurationManager is null) - return result; + { + if (result.IsSuccess) + return result; - if (result.IsValid) + StackFrame tokenValidationStackFrame = StackFrames.TokenValidationFailedNullConfigurationManager ??= new StackFrame(true); + return result.UnwrapError().AddStackFrame(tokenValidationStackFrame); + } + + if (result.IsSuccess) { // Set current configuration as LKG if it exists. if (currentConfiguration is not null) @@ -173,7 +149,7 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration, return result; } - if (TokenUtilities.IsRecoverableErrorType(result.ExceptionDetail?.Type)) + if (TokenUtilities.IsRecoverableErrorType(result.UnwrapError().Type)) { // If we were still unable to validate, attempt to refresh the configuration and validate using it // but ONLY if the currentConfiguration is not null. We want to avoid refreshing the configuration on @@ -193,7 +169,7 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration, await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration, callContext, cancellationToken).ConfigureAwait(false) : await ValidateJWSAsync(jsonWebToken, validationParameters, currentConfiguration, callContext, cancellationToken).ConfigureAwait(false); - if (result.IsValid) + if (result.IsSuccess) { validationParameters.ConfigurationManager.LastKnownGoodConfiguration = currentConfiguration; return result; @@ -205,7 +181,7 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration, { validationParameters.RefreshBeforeValidation = false; validationParameters.ValidateWithLKG = true; - ExceptionType recoverableExceptionType = result.ExceptionDetail?.Type ?? ExceptionType.Unknown; + ExceptionType recoverableExceptionType = result.UnwrapError().Type; BaseConfiguration[] validConfigurations = validationParameters.ConfigurationManager.GetValidLkgConfigurations(); for (int i = 0; i < validConfigurations.Length; i++) @@ -218,53 +194,63 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration, await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration, callContext, cancellationToken).ConfigureAwait(false) : await ValidateJWSAsync(jsonWebToken, validationParameters, currentConfiguration, callContext, cancellationToken).ConfigureAwait(false); - if (result.IsValid) + if (result.IsSuccess) return result; } } } } - return result; + // If we reach this point, the token validation failed and we should return the error. + StackFrame stackFrame = StackFrames.TokenValidationFailed ??= new StackFrame(true); + return result.UnwrapError().AddStackFrame(stackFrame); } - private async ValueTask ValidateJWEAsync( + private async ValueTask> ValidateJWEAsync( JsonWebToken jwtToken, ValidationParameters validationParameters, - BaseConfiguration configuration, + BaseConfiguration? configuration, CallContext callContext, CancellationToken cancellationToken) { Result decryptionResult = DecryptToken( jwtToken, validationParameters, configuration, callContext); - if (!decryptionResult.IsSuccess) - return new ValidationResult(jwtToken, this, validationParameters, decryptionResult.UnwrapError()); + { + StackFrame decryptionFailureStackFrame = StackFrames.DecryptionFailed ??= new StackFrame(true); + return decryptionResult.UnwrapError().AddStackFrame(decryptionFailureStackFrame); + } Result readResult = ReadToken(decryptionResult.UnwrapResult(), callContext); - if (!readResult.IsSuccess) - return new ValidationResult(jwtToken, this, validationParameters, readResult.UnwrapError()); - - JsonWebToken decryptedToken = readResult.UnwrapResult() as JsonWebToken; + { + StackFrame readFailureStackFrame = StackFrames.DecryptedReadFailed ??= new StackFrame(true); + return readResult.UnwrapError().AddStackFrame(readFailureStackFrame); + } - ValidationResult validationResult = - await ValidateJWSAsync(decryptedToken, validationParameters, configuration, callContext, cancellationToken) + JsonWebToken decryptedToken = (readResult.UnwrapResult() as JsonWebToken)!; + Result validationResult = + await ValidateJWSAsync(decryptedToken!, validationParameters, configuration, callContext, cancellationToken) .ConfigureAwait(false); - if (!validationResult.IsValid) - return validationResult; + if (!validationResult.IsSuccess) + { + StackFrame validationFailureStackFrame = StackFrames.JWEValidationFailed ??= new StackFrame(true); + return validationResult.UnwrapError().AddStackFrame(validationFailureStackFrame); + } + + JsonWebToken jsonWebToken = (validationResult.UnwrapResult().SecurityToken as JsonWebToken)!; - jwtToken.InnerToken = validationResult.SecurityToken as JsonWebToken; - jwtToken.Payload = (validationResult.SecurityToken as JsonWebToken).Payload; + jwtToken.InnerToken = jsonWebToken; + jwtToken.Payload = jsonWebToken.Payload; return validationResult; } - private async ValueTask ValidateJWSAsync( + private async ValueTask> ValidateJWSAsync( JsonWebToken jsonWebToken, ValidationParameters validationParameters, - BaseConfiguration configuration, + BaseConfiguration? configuration, CallContext callContext, CancellationToken cancellationToken) { @@ -275,8 +261,10 @@ private async ValueTask ValidateJWSAsync( notBefore, expires, jsonWebToken, validationParameters, callContext); if (!lifetimeValidationResult.IsSuccess) - return new ValidationResult( - jsonWebToken, this, validationParameters, lifetimeValidationResult.UnwrapError(), new StackFrame(true)); + { + StackFrame lifetimeValidationFailureStackFrame = StackFrames.LifetimeValidationFailed ??= new StackFrame(true); + return lifetimeValidationResult.UnwrapError().AddStackFrame(lifetimeValidationFailureStackFrame); + } if (jsonWebToken.Audiences is not IList tokenAudiences) tokenAudiences = jsonWebToken.Audiences.ToList(); @@ -285,136 +273,98 @@ private async ValueTask ValidateJWSAsync( tokenAudiences, jsonWebToken, validationParameters, callContext); if (!audienceValidationResult.IsSuccess) - return new ValidationResult( - jsonWebToken, this, validationParameters, audienceValidationResult.UnwrapError(), new StackFrame(true)) - { - ValidatedLifetime = lifetimeValidationResult.UnwrapResult() - }; + { + StackFrame audienceValidationFailureStackFrame = StackFrames.AudienceValidationFailed ??= new StackFrame(true); + return audienceValidationResult.UnwrapError().AddStackFrame(audienceValidationFailureStackFrame); + } Result issuerValidationResult = await validationParameters.IssuerValidatorAsync( jsonWebToken.Issuer, jsonWebToken, validationParameters, callContext, cancellationToken) .ConfigureAwait(false); if (!issuerValidationResult.IsSuccess) - return new ValidationResult( - jsonWebToken, this, validationParameters, issuerValidationResult.UnwrapError(), new StackFrame(true)) - { - ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), - ValidatedAudience = audienceValidationResult.UnwrapResult() - }; + { + StackFrame issuerValidationFailureStackFrame = StackFrames.IssuerValidationFailed ??= new StackFrame(true); + return issuerValidationResult.UnwrapError().AddStackFrame(issuerValidationFailureStackFrame); + } Result replayValidationResult = validationParameters.TokenReplayValidator( expires, jsonWebToken.EncodedToken, validationParameters, callContext); if (!replayValidationResult.IsSuccess) - return new ValidationResult( - jsonWebToken, this, validationParameters, replayValidationResult.UnwrapError(), new StackFrame(true)) - { - ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), - ValidatedAudience = audienceValidationResult.UnwrapResult(), - ValidatedIssuer = issuerValidationResult.UnwrapResult() - }; + { + StackFrame replayValidationFailureStackFrame = StackFrames.ReplayValidationFailed ??= new StackFrame(true); + return replayValidationResult.UnwrapError().AddStackFrame(replayValidationFailureStackFrame); + } - ValidationResult actorValidationResult = null; + Result? actorValidationResult = null; // actor validation if (validationParameters.ValidateActor && !string.IsNullOrWhiteSpace(jsonWebToken.Actor)) { Result actorReadingResult = ReadToken(jsonWebToken.Actor, callContext); if (!actorReadingResult.IsSuccess) - return new ValidationResult( - jsonWebToken, this, validationParameters, actorReadingResult.UnwrapError(), new StackFrame(true)) - { - ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), - ValidatedAudience = audienceValidationResult.UnwrapResult(), - ValidatedIssuer = issuerValidationResult.UnwrapResult(), - ValidatedTokenReplayExpirationTime = replayValidationResult.UnwrapResult() - }; + { + StackFrame actorReadingFailureStackFrame = StackFrames.ActorReadFailed ??= new StackFrame(true); + return actorReadingResult.UnwrapError().AddStackFrame(actorReadingFailureStackFrame); + } - JsonWebToken actorToken = actorReadingResult.UnwrapResult() as JsonWebToken; + JsonWebToken actorToken = (actorReadingResult.UnwrapResult() as JsonWebToken)!; ValidationParameters actorParameters = validationParameters.ActorValidationParameters; - actorValidationResult = + Result innerActorValidationResult = await ValidateJWSAsync(actorToken, actorParameters, configuration, callContext, cancellationToken) .ConfigureAwait(false); - // Consider adding a new ValidationResult type for actor validation - // that wraps the actorValidationResult.ValidationResults - if (!actorValidationResult.IsValid) - return new ValidationResult( - jsonWebToken, this, validationParameters, actorValidationResult.ExceptionDetail, new StackFrame(true)) - { - ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), - ValidatedAudience = audienceValidationResult.UnwrapResult(), - ValidatedIssuer = issuerValidationResult.UnwrapResult(), - ValidatedTokenReplayExpirationTime = replayValidationResult.UnwrapResult(), - ActorValidationResult = actorValidationResult - }; + if (!innerActorValidationResult.IsSuccess) + { + StackFrame actorValidationFailureStackFrame = StackFrames.ActorValidationFailed ??= new StackFrame(true); + return innerActorValidationResult.UnwrapError().AddStackFrame(actorValidationFailureStackFrame); + } + + actorValidationResult = innerActorValidationResult; } Result typeValidationResult = validationParameters.TypeValidator( jsonWebToken.Typ, jsonWebToken, validationParameters, callContext); - if (!typeValidationResult.IsSuccess) - return new ValidationResult(jsonWebToken, this, validationParameters, typeValidationResult.UnwrapError()) - { - ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), - ValidatedAudience = audienceValidationResult.UnwrapResult(), - ValidatedIssuer = issuerValidationResult.UnwrapResult(), - ValidatedTokenReplayExpirationTime = replayValidationResult.UnwrapResult(), - ActorValidationResult = actorValidationResult - }; + { + StackFrame typeValidationFailureStackFrame = StackFrames.TypeValidationFailed ??= new StackFrame(true); + return typeValidationResult.UnwrapError().AddStackFrame(typeValidationFailureStackFrame); + } // The signature validation delegate is yet to be migrated to ValidationParameters. Result signatureValidationResult = ValidateSignature( jsonWebToken, validationParameters, configuration, callContext); - if (!signatureValidationResult.IsSuccess) { - StackFrame stackFrame = StackFrames.SignatureValidationFailed ??= new StackFrame(true); - return new ValidationResult( - jsonWebToken, this, validationParameters, signatureValidationResult.UnwrapError(), stackFrame) - { - ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), - ValidatedAudience = audienceValidationResult.UnwrapResult(), - ValidatedIssuer = issuerValidationResult.UnwrapResult(), - ValidatedTokenReplayExpirationTime = replayValidationResult.UnwrapResult(), - ActorValidationResult = actorValidationResult, - ValidatedTokenType = typeValidationResult.UnwrapResult() - }; + StackFrame signatureValidationFailureStackFrame = StackFrames.SignatureValidationFailed ??= new StackFrame(true); + return signatureValidationResult.UnwrapError().AddStackFrame(signatureValidationFailureStackFrame); } Result issuerSigningKeyValidationResult = validationParameters.IssuerSigningKeyValidator( signatureValidationResult.UnwrapResult(), jsonWebToken, validationParameters, configuration, callContext); - if (!issuerSigningKeyValidationResult.IsSuccess) - return new ValidationResult( - jsonWebToken, this, validationParameters, issuerSigningKeyValidationResult.UnwrapError(), new StackFrame(true)) - { - ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), - ValidatedAudience = audienceValidationResult.UnwrapResult(), - ValidatedIssuer = issuerValidationResult.UnwrapResult(), - ValidatedTokenReplayExpirationTime = replayValidationResult.UnwrapResult(), - ActorValidationResult = actorValidationResult, - ValidatedTokenType = typeValidationResult.UnwrapResult(), - ValidatedSigningKey = signatureValidationResult.UnwrapResult() - }; - - return new(jsonWebToken, this, validationParameters) + { + StackFrame issuerSigningKeyValidationFailureStackFrame = StackFrames.IssuerSigningKeyValidationFailed ??= new StackFrame(true); + return issuerSigningKeyValidationResult.UnwrapError().AddStackFrame(issuerSigningKeyValidationFailureStackFrame); + } + + return new ValidationResult(jsonWebToken, this, validationParameters) { ValidatedLifetime = lifetimeValidationResult.UnwrapResult(), ValidatedAudience = audienceValidationResult.UnwrapResult(), ValidatedIssuer = issuerValidationResult.UnwrapResult(), ValidatedTokenReplayExpirationTime = replayValidationResult.UnwrapResult(), - ActorValidationResult = actorValidationResult, + ActorValidationResult = actorValidationResult?.UnwrapResult(), ValidatedTokenType = typeValidationResult.UnwrapResult(), ValidatedSigningKey = signatureValidationResult.UnwrapResult(), ValidatedSigningKeyLifetime = issuerSigningKeyValidationResult.UnwrapResult() }; } - private static async Task GetCurrentConfigurationAsync(ValidationParameters validationParameters) + private static async Task GetCurrentConfigurationAsync(ValidationParameters validationParameters) { - BaseConfiguration currentConfiguration = null; + BaseConfiguration? currentConfiguration = null; if (validationParameters.ConfigurationManager is not null) { try @@ -437,3 +387,4 @@ private static async Task GetCurrentConfigurationAsync(Valida } } } +#nullable restore diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.StackFrames.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.StackFrames.cs new file mode 100644 index 0000000000..6f34cc0e10 --- /dev/null +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.StackFrames.cs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Diagnostics; +using Microsoft.IdentityModel.Tokens; + +#nullable enable + +namespace Microsoft.IdentityModel.JsonWebTokens +{ + public partial class JsonWebTokenHandler : TokenHandler + { + // Cached stack frames to build exceptions from validation errors + internal static class StackFrames + { + // ValidateTokenAsync from string + internal static StackFrame? TokenStringNull; + internal static StackFrame? TokenStringValidationParametersNull; + internal static StackFrame? InvalidTokenLength; + internal static StackFrame? TokenStringValidationFailed; + internal static StackFrame? TokenStringReadFailed; + // ValidateTokenAsync from SecurityToken + internal static StackFrame? TokenNull; + internal static StackFrame? TokenValidationParametersNull; + internal static StackFrame? TokenNotJWT; + internal static StackFrame? TokenValidationFailedNullConfigurationManager; + internal static StackFrame? TokenValidationFailed; + // ValidateJWEAsync + internal static StackFrame? DecryptionFailed; + internal static StackFrame? DecryptedReadFailed; + internal static StackFrame? JWEValidationFailed; + // ValidateJWSAsync + internal static StackFrame? LifetimeValidationFailed; + internal static StackFrame? AudienceValidationFailed; + internal static StackFrame? IssuerValidationFailed; + internal static StackFrame? ReplayValidationFailed; + internal static StackFrame? ActorReadFailed; + internal static StackFrame? ActorValidationFailed; + internal static StackFrame? TypeValidationFailed; + internal static StackFrame? SignatureValidationFailed; + internal static StackFrame? IssuerSigningKeyValidationFailed; + } + } +} +#nullable restore diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs index aa89ff22c1..9e0ccdbbd7 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs @@ -78,6 +78,17 @@ public Exception GetException() /// public IList StackFrames { get; } + /// + /// Adds a stack frame to the list of stack frames and returns the updated object. + /// + /// The to be added. + /// + public ExceptionDetail AddStackFrame(StackFrame stackFrame) + { + StackFrames.Add(stackFrame); + return this; + } + private Exception ExceptionFromType(ExceptionType exceptionType, Exception innerException) { switch (exceptionType) diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs index 6eaf7eddb9..f0f05fdeb9 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs @@ -28,35 +28,10 @@ internal ValidationResult( ValidationParameters validationParameters) { TokenHandler = tokenHandler ?? throw new ArgumentNullException("TokenHandler cannot be null."); - SecurityToken = securityToken; - ValidationParameters = validationParameters; - IsValid = true; + SecurityToken = securityToken ?? throw new ArgumentNullException("SecurityToken cannot be null."); + ValidationParameters = validationParameters ?? throw new ArgumentNullException("ValidationParameters cannot be null."); ; } - public ValidationResult( - SecurityToken? securityToken, - TokenHandler tokenHandler, - ValidationParameters? validationParameters, - ExceptionDetail exceptionDetail, - StackFrame? stackFrame = null) - { - TokenHandler = tokenHandler ?? throw new ArgumentNullException("TokenHandler cannot be null."); - SecurityToken = securityToken; - ValidationParameters = validationParameters; - ExceptionDetail = exceptionDetail; - IsValid = false; - - if (stackFrame != null) - ExceptionDetail.StackFrames.Add(stackFrame); - } - - public ExceptionDetail? ExceptionDetail { get; private set; } - - /// - /// True if the token was successfully validated, false otherwise. - /// - public bool IsValid { get; private set; } - /// /// Logs the validation result. /// @@ -67,16 +42,16 @@ public void Log() // TODO - Do we need this, how will it work? } - public SecurityToken? SecurityToken { get; private set; } + public SecurityToken SecurityToken { get; private set; } public TokenHandler TokenHandler { get; private set; } - public ValidationParameters? ValidationParameters { get; private set; } + public ValidationParameters ValidationParameters { get; private set; } #region Validation Results public ValidationResult? ActorValidationResult { get; internal set; } public string? ValidatedAudience { get; internal set; } - public ValidatedIssuer ValidatedIssuer { get; internal set; } + public ValidatedIssuer? ValidatedIssuer { get; internal set; } public ValidatedLifetime? ValidatedLifetime { get; internal set; } public DateTime? ValidatedTokenReplayExpirationTime { get; internal set; } public ValidatedTokenType? ValidatedTokenType { get; internal set; } @@ -102,11 +77,11 @@ public void Log() /// /// The created from the validated security token. /// - public IDictionary? Claims + public IDictionary Claims { get { - if (_claims is null && ClaimsIdentity is not null) + if (_claims is null) { Interlocked.CompareExchange(ref _claims, TokenUtilities.CreateDictionaryFromClaims(ClaimsIdentity.Claims), null); } @@ -156,11 +131,7 @@ internal ClaimsIdentity ClaimsIdentityNoLocking { Debug.Assert(_claimsIdentity is null); - if (IsValid) - { - _claimsIdentity = TokenHandler.CreateClaimsIdentityInternal(SecurityToken, ValidationParameters, ValidatedIssuer.Issuer); - } - + _claimsIdentity = TokenHandler.CreateClaimsIdentityInternal(SecurityToken, ValidationParameters, ValidatedIssuer?.Issuer); _claimsIdentityInitialized = true; } From 9ba4c7b16a461c7f5d5bcc38fd7ba0d34eaccacd Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Mon, 26 Aug 2024 14:49:58 +0100 Subject: [PATCH 26/32] Added stack frames for ReadToken and DecryptToken --- .../JsonWebTokenHandler.DecryptToken.cs | 25 +++++++++++++++---- .../JsonWebTokenHandler.ReadToken.cs | 8 ++++-- ...bTokenHandler.ValidateToken.StackFrames.cs | 9 +++++++ 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs index 99572fcfd1..c3152caa3d 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs @@ -31,34 +31,49 @@ internal Result DecryptToken( CallContext? callContext) { if (jwtToken == null) + { + StackFrame tokenNullStackFrame = StackFrames.DecryptionTokenNull ??= new StackFrame(); return ExceptionDetail.NullParameter( nameof(jwtToken), - new StackFrame(true)); + tokenNullStackFrame); + } if (validationParameters == null) + { + StackFrame validationParametersNullStackFrame = StackFrames.DecryptionValidationParametersNull ??= new StackFrame(); return ExceptionDetail.NullParameter( nameof(validationParameters), - new StackFrame(true)); + validationParametersNullStackFrame); + } if (string.IsNullOrEmpty(jwtToken.Enc)) + { + StackFrame headerMissingStackFrame = StackFrames.DecryptionHeaderMissing ??= new StackFrame(); return new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10612), ExceptionType.SecurityToken, - new StackFrame(true)); + headerMissingStackFrame); + } (IList? contentEncryptionKeys, ExceptionDetail? exceptionDetail) result = GetContentEncryptionKeys(jwtToken, validationParameters, configuration, callContext); if (result.exceptionDetail != null) - return result.exceptionDetail; + { + StackFrame decryptionGetKeysStackFrame = StackFrames.DecryptionGetEncryptionKeys ??= new StackFrame(); + return result.exceptionDetail.AddStackFrame(decryptionGetKeysStackFrame); + } if (result.contentEncryptionKeys == null) + { + StackFrame noKeysTriedStackFrame = StackFrames.DecryptionNoKeysTried ??= new StackFrame(); return new ExceptionDetail( new MessageDetail( TokenLogMessages.IDX10609, LogHelper.MarkAsSecurityArtifact(jwtToken, JwtTokenUtilities.SafeLogJwtToken)), ExceptionType.SecurityTokenDecryptionFailed, - new StackFrame(true)); + noKeysTriedStackFrame); + } return JwtTokenUtilities.DecryptJwtToken( jwtToken, diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs index 54c67ca302..9ba1a56033 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs @@ -28,9 +28,12 @@ internal static Result ReadToken( #pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging { if (String.IsNullOrEmpty(token)) + { + StackFrame nullTokenStackFrame = StackFrames.ReadTokenNullOrEmpty ?? new StackFrame(true); return ExceptionDetail.NullParameter( nameof(token), - new StackFrame(true)); + nullTokenStackFrame); + } try { @@ -41,10 +44,11 @@ internal static Result ReadToken( catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { + StackFrame malformedTokenStackFrame = StackFrames.ReadTokenMalformed ?? new StackFrame(true); return new ExceptionDetail( new MessageDetail(LogMessages.IDX14107), ExceptionType.SecurityTokenMalformed, - new StackFrame(true), + malformedTokenStackFrame, ex); } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.StackFrames.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.StackFrames.cs index 6f34cc0e10..282762a96d 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.StackFrames.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.StackFrames.cs @@ -39,6 +39,15 @@ internal static class StackFrames internal static StackFrame? TypeValidationFailed; internal static StackFrame? SignatureValidationFailed; internal static StackFrame? IssuerSigningKeyValidationFailed; + // DecryptToken + internal static StackFrame? DecryptionTokenNull; + internal static StackFrame? DecryptionValidationParametersNull; + internal static StackFrame? DecryptionHeaderMissing; + internal static StackFrame? DecryptionGetEncryptionKeys; + internal static StackFrame? DecryptionNoKeysTried; + // ReadToken + internal static StackFrame? ReadTokenNullOrEmpty; + internal static StackFrame? ReadTokenMalformed; } } } From 168ee84ac60f4e87acab4a0b2a6fb05371b0d898 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Mon, 26 Aug 2024 15:22:25 +0100 Subject: [PATCH 27/32] Added ValidationFailureType to ExceptionDetail --- .../JsonWebTokenHandler.DecryptToken.cs | 16 +++++++++------ .../JsonWebTokenHandler.ReadToken.cs | 1 + .../JsonWebTokenHandler.ValidateSignature.cs | 10 ++++++++++ ...nWebTokenHandler.ValidateToken.Internal.cs | 2 ++ ...bTokenHandler.ValidateToken.StackFrames.cs | 1 + .../JwtTokenUtilities.DecryptTokenResult.cs | 1 + .../JwtTokenUtilities.cs | 3 +++ .../Results/Details/ExceptionDetail.cs | 20 ++++++++++++++++--- .../Validation/ValidationFailureType.cs | 13 +++--------- .../Validation/Validators.Algorithm.cs | 1 + .../Validation/Validators.Audience.cs | 3 +++ .../Validation/Validators.Issuer.cs | 3 +++ .../Validation/Validators.IssuerSigningKey.cs | 3 +++ .../Validation/Validators.Lifetime.cs | 4 ++++ .../Validation/Validators.TokenReplay.cs | 3 +++ .../Validation/Validators.TokenType.cs | 2 ++ 16 files changed, 67 insertions(+), 19 deletions(-) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs index c3152caa3d..eed4e39e5e 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs @@ -32,7 +32,7 @@ internal Result DecryptToken( { if (jwtToken == null) { - StackFrame tokenNullStackFrame = StackFrames.DecryptionTokenNull ??= new StackFrame(); + StackFrame tokenNullStackFrame = StackFrames.DecryptionTokenNull ??= new StackFrame(true); return ExceptionDetail.NullParameter( nameof(jwtToken), tokenNullStackFrame); @@ -40,7 +40,7 @@ internal Result DecryptToken( if (validationParameters == null) { - StackFrame validationParametersNullStackFrame = StackFrames.DecryptionValidationParametersNull ??= new StackFrame(); + StackFrame validationParametersNullStackFrame = StackFrames.DecryptionValidationParametersNull ??= new StackFrame(true); return ExceptionDetail.NullParameter( nameof(validationParameters), validationParametersNullStackFrame); @@ -48,9 +48,10 @@ internal Result DecryptToken( if (string.IsNullOrEmpty(jwtToken.Enc)) { - StackFrame headerMissingStackFrame = StackFrames.DecryptionHeaderMissing ??= new StackFrame(); + StackFrame headerMissingStackFrame = StackFrames.DecryptionHeaderMissing ??= new StackFrame(true); return new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10612), + ValidationFailureType.TokenDecryptionFailed, ExceptionType.SecurityToken, headerMissingStackFrame); } @@ -60,17 +61,18 @@ internal Result DecryptToken( if (result.exceptionDetail != null) { - StackFrame decryptionGetKeysStackFrame = StackFrames.DecryptionGetEncryptionKeys ??= new StackFrame(); + StackFrame decryptionGetKeysStackFrame = StackFrames.DecryptionGetEncryptionKeys ??= new StackFrame(true); return result.exceptionDetail.AddStackFrame(decryptionGetKeysStackFrame); } if (result.contentEncryptionKeys == null) { - StackFrame noKeysTriedStackFrame = StackFrames.DecryptionNoKeysTried ??= new StackFrame(); + StackFrame noKeysTriedStackFrame = StackFrames.DecryptionNoKeysTried ??= new StackFrame(true); return new ExceptionDetail( new MessageDetail( TokenLogMessages.IDX10609, LogHelper.MarkAsSecurityArtifact(jwtToken, JwtTokenUtilities.SafeLogJwtToken)), + ValidationFailureType.TokenDecryptionFailed, ExceptionType.SecurityTokenDecryptionFailed, noKeysTriedStackFrame); } @@ -205,14 +207,16 @@ internal Result DecryptToken( return (unwrappedKeys, null); else { + StackFrame decryptionKeyUnwrapFailedStackFrame = StackFrames.DecryptionKeyUnwrapFailed ??= new StackFrame(true); ExceptionDetail exceptionDetail = new( new MessageDetail( TokenLogMessages.IDX10618, keysAttempted?.ToString() ?? "", exceptionStrings?.ToString() ?? "", LogHelper.MarkAsSecurityArtifact(jwtToken, JwtTokenUtilities.SafeLogJwtToken)), + ValidationFailureType.TokenDecryptionFailed, ExceptionType.SecurityTokenKeyWrap, - new System.Diagnostics.StackFrame(), + decryptionKeyUnwrapFailedStackFrame, null); return (null, exceptionDetail); diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs index 9ba1a56033..ac2ea435d1 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs @@ -47,6 +47,7 @@ internal static Result ReadToken( StackFrame malformedTokenStackFrame = StackFrames.ReadTokenMalformed ?? new StackFrame(true); return new ExceptionDetail( new MessageDetail(LogMessages.IDX14107), + ValidationFailureType.TokenReadingFailed, ExceptionType.SecurityTokenMalformed, malformedTokenStackFrame, ex); diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs index ba92e216d2..62df40a484 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs @@ -61,6 +61,7 @@ internal static Result ValidateSignature( LogHelper.MarkAsSecurityArtifact( jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), + ValidationFailureType.SignatureValidationFailed, ExceptionType.SecurityTokenInvalidSignature, new StackFrame(true)); @@ -99,6 +100,7 @@ internal static Result ValidateSignature( StackFrame stackFrame = SignatureStackFrames.NoKeysProvided ??= new StackFrame(true); return new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10500), + ValidationFailureType.SignatureValidationFailed, ExceptionType.SecurityTokenSignatureKeyNotFound, stackFrame); } @@ -135,6 +137,7 @@ private static Result ValidateSignatureUsingAllKey if (vpFailedResult is null && configFailedResult is null) // No keys were attempted return new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10500), + ValidationFailureType.SignatureValidationFailed, ExceptionType.SecurityTokenSignatureKeyNotFound, new StackFrame(true)); @@ -216,6 +219,7 @@ private static Result ValidateSignatureWithKey( TokenLogMessages.IDX10400, LogHelper.MarkAsNonPII(jsonWebToken.Alg), key), + ValidationFailureType.SignatureValidationFailed, ExceptionType.SecurityTokenInvalidAlgorithm, new StackFrame(true)); } @@ -239,6 +243,7 @@ private static Result ValidateSignatureWithKey( TokenLogMessages.IDX10636, key?.ToString() ?? "Null", LogHelper.MarkAsNonPII(jsonWebToken.Alg)), + ValidationFailureType.SignatureValidationFailed, ExceptionType.InvalidOperation, new StackFrame(true)); @@ -261,6 +266,7 @@ private static Result ValidateSignatureWithKey( LogHelper.MarkAsSecurityArtifact( jsonWebToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), + ValidationFailureType.SignatureValidationFailed, ExceptionType.SecurityTokenInvalidSignature, new StackFrame(true)); } @@ -274,6 +280,7 @@ private static Result ValidateSignatureWithKey( LogHelper.MarkAsSecurityArtifact( jsonWebToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), + ValidationFailureType.SignatureValidationFailed, ExceptionType.SecurityTokenInvalidSignature, new StackFrame(true), ex); @@ -314,6 +321,7 @@ private static ExceptionDetail GetSignatureValidationError( LogHelper.MarkAsNonPII(jwtToken.Kid), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), + ValidationFailureType.SignatureValidationFailed, ExceptionType.SecurityTokenSignatureKeyNotFound, new StackFrame(true)); } @@ -328,6 +336,7 @@ private static ExceptionDetail GetSignatureValidationError( LogHelper.MarkAsNonPII(numKeysInConfiguration), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), + ValidationFailureType.SignatureValidationFailed, ExceptionType.SecurityTokenSignatureKeyNotFound, new StackFrame(true)); @@ -339,6 +348,7 @@ private static ExceptionDetail GetSignatureValidationError( LogHelper.MarkAsNonPII(numKeysInConfiguration), exceptionStrings.ToString(), LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)), + ValidationFailureType.SignatureValidationFailed, ExceptionType.SecurityTokenSignatureKeyNotFound, new StackFrame(true)); } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs index 2d412fdcd8..9ce61dc2e5 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs @@ -66,6 +66,7 @@ internal async Task> ValidateTokenAsyn TokenLogMessages.IDX10209, LogHelper.MarkAsNonPII(token.Length), LogHelper.MarkAsNonPII(MaximumTokenSizeInBytes)), + ValidationFailureType.InvalidSecurityToken, ExceptionType.InvalidArgument, invalidTokenLengthStackFrame); } @@ -119,6 +120,7 @@ internal async Task> ValidateTokenAsyn StackFrame notJwtStackFrame = StackFrames.TokenNotJWT ??= new StackFrame(true); return new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10001, nameof(token), nameof(JsonWebToken)), + ValidationFailureType.InvalidSecurityToken, ExceptionType.InvalidArgument, notJwtStackFrame); } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.StackFrames.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.StackFrames.cs index 282762a96d..9f6ff9324c 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.StackFrames.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.StackFrames.cs @@ -45,6 +45,7 @@ internal static class StackFrames internal static StackFrame? DecryptionHeaderMissing; internal static StackFrame? DecryptionGetEncryptionKeys; internal static StackFrame? DecryptionNoKeysTried; + internal static StackFrame? DecryptionKeyUnwrapFailed; // ReadToken internal static StackFrame? ReadTokenNullOrEmpty; internal static StackFrame? ReadTokenMalformed; diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs index 31f2f51593..bd30f17651 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs @@ -123,6 +123,7 @@ internal static Result DecryptJwtToken( { return new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10679, zipAlgorithm), + ValidationFailureType.TokenDecryptionFailed, ExceptionType.SecurityTokenDecompressionFailed, new StackFrame(true), ex); diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs index 59231a8652..e92d0e1d48 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs @@ -371,6 +371,7 @@ private static ExceptionDetail GetDecryptionError( keysAttempted.ToString(), exceptionStrings?.ToString() ?? string.Empty, LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken)), + ValidationFailureType.TokenDecryptionFailed, ExceptionType.SecurityTokenDecryptionFailed, new StackFrame(true), null); @@ -380,6 +381,7 @@ private static ExceptionDetail GetDecryptionError( TokenLogMessages.IDX10619, LogHelper.MarkAsNonPII(decryptionParameters.Alg), LogHelper.MarkAsNonPII(decryptionParameters.Enc)), + ValidationFailureType.TokenDecryptionFailed, ExceptionType.SecurityTokenDecryptionFailed, new StackFrame(true)); else @@ -387,6 +389,7 @@ private static ExceptionDetail GetDecryptionError( new MessageDetail( TokenLogMessages.IDX10609, LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken)), + ValidationFailureType.TokenDecryptionFailed, ExceptionType.SecurityTokenDecryptionFailed, new StackFrame(true)); } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs index 9e0ccdbbd7..4e884a997b 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/ExceptionDetail.cs @@ -16,10 +16,11 @@ internal class ExceptionDetail /// Creates an instance of /// /// contains information about the exception that is used to generate the exception message. + /// is the type of validation failure that occurred. /// is the type of exception that occurred. /// is the stack frame where the exception occurred. - public ExceptionDetail(MessageDetail MessageDetail, ExceptionType exceptionType, StackFrame stackFrame) - : this(MessageDetail, exceptionType, stackFrame, null) + public ExceptionDetail(MessageDetail MessageDetail, ValidationFailureType failureType, ExceptionType exceptionType, StackFrame stackFrame) + : this(MessageDetail, failureType, exceptionType, stackFrame, null) { } @@ -27,14 +28,21 @@ public ExceptionDetail(MessageDetail MessageDetail, ExceptionType exceptionType, /// Creates an instance of /// /// contains information about the exception that is used to generate the exception message. + /// is the type of validation failure that occurred. /// is the type of exception that occurred. /// is the stack frame where the exception occurred. /// is the inner exception that occurred. - public ExceptionDetail(MessageDetail messageDetail, ExceptionType exceptionType, StackFrame stackFrame, Exception innerException) + public ExceptionDetail( + MessageDetail messageDetail, + ValidationFailureType failureType, + ExceptionType exceptionType, + StackFrame stackFrame, + Exception innerException) { Type = exceptionType; InnerException = innerException; MessageDetail = messageDetail; + FailureType = failureType; StackFrames = new List(4) { stackFrame @@ -56,8 +64,14 @@ public Exception GetException() internal static ExceptionDetail NullParameter(string parameterName, StackFrame stackFrame) => new ExceptionDetail( MessageDetail.NullParameter(parameterName), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, stackFrame); + /// + /// Gets the type of validation failure that occurred. + /// + public ValidationFailureType FailureType { get; } + /// /// Gets the type of exception that occurred. /// diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/ValidationFailureType.cs b/src/Microsoft.IdentityModel.Tokens/Validation/ValidationFailureType.cs index e7f4ca7f40..20b4224cc5 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/ValidationFailureType.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/ValidationFailureType.cs @@ -88,16 +88,9 @@ private class TokenReadingFailure : ValidationFailureType { internal TokenReadin private class TokenDecryptionFailure : ValidationFailureType { internal TokenDecryptionFailure(string name) : base(name) { } } /// - /// Defines a type that represents that no evaluation has taken place. + /// Defines a type that represents that a token is invalid. /// - public static readonly ValidationFailureType ValidationNotEvaluated = new NotEvaluated("NotEvaluated"); - private class NotEvaluated : ValidationFailureType { internal NotEvaluated(string name) : base(name) { } } - - /// - /// Defines a type that represents that no evaluation has taken place. - /// - public static readonly ValidationFailureType ValidationSucceeded = new Succeeded("Succeeded"); - private class Succeeded : ValidationFailureType { internal Succeeded(string name) : base(name) { } } - + public static readonly ValidationFailureType InvalidSecurityToken = new InvalidSecurityTokenFailure("InvalidSecurityToken"); + private class InvalidSecurityTokenFailure : ValidationFailureType { internal InvalidSecurityTokenFailure(string name) : base(name) { } } } } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs index c32fc4a2f1..15fd8baf82 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs @@ -58,6 +58,7 @@ internal static Result ValidateAlgorithm( new MessageDetail( LogMessages.IDX10696, LogHelper.MarkAsNonPII(algorithm)), + ValidationFailureType.AlgorithmValidationFailed, ExceptionType.SecurityTokenInvalidAlgorithm, new StackFrame(true)); diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs index e193cacc64..f9b5fccb2b 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Audience.cs @@ -54,12 +54,14 @@ internal static Result ValidateAudience(IList t if (tokenAudiences == null) return new ExceptionDetail( new MessageDetail(LogMessages.IDX10207), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, new StackFrame(true)); if (tokenAudiences.Count == 0) return new ExceptionDetail( new MessageDetail(LogMessages.IDX10206), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, new StackFrame(true)); @@ -72,6 +74,7 @@ internal static Result ValidateAudience(IList t LogMessages.IDX10215, LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(tokenAudiences)), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidAudiences))), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, new StackFrame(true)); } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs index 437e638736..cf8e5f5894 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs @@ -64,6 +64,7 @@ internal static async Task> ValidateIss { return new ExceptionDetail( new MessageDetail(LogMessages.IDX10211), + ValidationFailureType.IssuerValidationFailed, ExceptionType.SecurityTokenInvalidIssuer, new StackFrame(true)); } @@ -86,6 +87,7 @@ internal static async Task> ValidateIss if (validationParameters.ValidIssuers.Count == 0 && string.IsNullOrWhiteSpace(configuration?.Issuer)) return new ExceptionDetail( new MessageDetail(LogMessages.IDX10211), + ValidationFailureType.IssuerValidationFailed, ExceptionType.SecurityTokenInvalidIssuer, new StackFrame(true)); @@ -135,6 +137,7 @@ internal static async Task> ValidateIss LogHelper.MarkAsNonPII(issuer), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidIssuers)), LogHelper.MarkAsNonPII(configuration?.Issuer)), + ValidationFailureType.IssuerValidationFailed, ExceptionType.SecurityTokenInvalidIssuer, new StackFrame(true)); } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs index 025aaa4f8e..6cabad2b25 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs @@ -63,6 +63,7 @@ internal static Result ValidateIss if (securityKey == null) return new ExceptionDetail( new MessageDetail(LogMessages.IDX10253, nameof(securityKey)), + ValidationFailureType.SigningKeyValidationFailed, ExceptionType.ArgumentNull, new StackFrame(true)); @@ -103,6 +104,7 @@ internal static Result ValidateIss LogMessages.IDX10248, LogHelper.MarkAsNonPII(notBeforeUtc), LogHelper.MarkAsNonPII(utcNow)), + ValidationFailureType.SigningKeyValidationFailed, ExceptionType.SecurityTokenInvalidSigningKey, new StackFrame(true)); @@ -116,6 +118,7 @@ internal static Result ValidateIss LogMessages.IDX10249, LogHelper.MarkAsNonPII(notAfterUtc), LogHelper.MarkAsNonPII(utcNow)), + ValidationFailureType.SigningKeyValidationFailed, ExceptionType.SecurityTokenInvalidSigningKey, new StackFrame(true)); diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs index ccb13f468d..7e10402857 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Lifetime.cs @@ -67,6 +67,7 @@ internal static Result ValidateLifetime( new MessageDetail( LogMessages.IDX10225, LogHelper.MarkAsNonPII(securityToken == null ? "null" : securityToken.GetType().ToString())), + ValidationFailureType.LifetimeValidationFailed, ExceptionType.SecurityTokenNoExpiration, new StackFrame(true)); @@ -76,6 +77,7 @@ internal static Result ValidateLifetime( LogMessages.IDX10224, LogHelper.MarkAsNonPII(notBefore.Value), LogHelper.MarkAsNonPII(expires.Value)), + ValidationFailureType.LifetimeValidationFailed, ExceptionType.SecurityTokenInvalidLifetime, new StackFrame(true)); @@ -86,6 +88,7 @@ internal static Result ValidateLifetime( LogMessages.IDX10222, LogHelper.MarkAsNonPII(notBefore.Value), LogHelper.MarkAsNonPII(utcNow)), + ValidationFailureType.LifetimeValidationFailed, ExceptionType.SecurityTokenNotYetValid, new StackFrame(true)); @@ -95,6 +98,7 @@ internal static Result ValidateLifetime( LogMessages.IDX10223, LogHelper.MarkAsNonPII(expires.Value), LogHelper.MarkAsNonPII(utcNow)), + ValidationFailureType.LifetimeValidationFailed, ExceptionType.SecurityTokenExpired, new StackFrame(true)); diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs index c74114e147..f110c8eb02 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs @@ -62,6 +62,7 @@ public static partial class Validators new MessageDetail( LogMessages.IDX10227, LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), + ValidationFailureType.TokenReplayValidationFailed, ExceptionType.SecurityTokenReplayDetected, new StackFrame(true)); @@ -70,6 +71,7 @@ public static partial class Validators new MessageDetail( LogMessages.IDX10228, LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), + ValidationFailureType.TokenReplayValidationFailed, ExceptionType.SecurityTokenReplayDetected, new StackFrame(true)); @@ -78,6 +80,7 @@ public static partial class Validators new MessageDetail( LogMessages.IDX10229, LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())), + ValidationFailureType.TokenReplayValidationFailed, ExceptionType.SecurityTokenReplayAddFailed, new StackFrame(true)); } diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs index 579463ccce..b6ce0a9d28 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs @@ -64,6 +64,7 @@ internal static Result ValidateTokenType( if (string.IsNullOrEmpty(type)) return new ExceptionDetail( new MessageDetail(LogMessages.IDX10256), + ValidationFailureType.TokenTypeValidationFailed, ExceptionType.SecurityTokenInvalidType, new StackFrame(true)); @@ -74,6 +75,7 @@ internal static Result ValidateTokenType( LogMessages.IDX10257, LogHelper.MarkAsNonPII(type), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidTypes))), + ValidationFailureType.TokenTypeValidationFailed, ExceptionType.SecurityTokenInvalidType, new StackFrame(true)); } From b407bad685417bf4ee8b420834e55aa7e9cbf076 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Mon, 26 Aug 2024 17:02:50 +0100 Subject: [PATCH 28/32] Updated tests to use ValidationFailureType --- .../JsonWebTokenHandler.DecryptTokenTests.cs | 26 +++++++++++++------ .../JsonWebTokenHandler.ReadTokenTests.cs | 11 +++++++- ...nWebTokenHandler.ValidateSignatureTests.cs | 14 +++++++++- .../AlgorithmValidationResultTests.cs | 10 ++++++- .../AudienceValidationResultTests.cs | 26 ++++++++++++++++++- .../Validation/ExceptionDetailsTests.cs | 2 ++ .../Validation/IssuerValidationResultTests.cs | 12 ++++++++- .../LifetimeValidationResultTests.cs | 21 ++++++++++----- .../Validation/ReplayValidationResultTests.cs | 14 +++++++++- .../SigningKeyValidationResultTests.cs | 14 +++++++++- .../TokenTypeValidationResultTests.cs | 13 +++++++++- 11 files changed, 140 insertions(+), 23 deletions(-) diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.DecryptTokenTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.DecryptTokenTests.cs index f472508937..9f3604a566 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.DecryptTokenTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.DecryptTokenTests.cs @@ -48,7 +48,13 @@ public void DecryptToken(TokenDecryptingTheoryData theoryData) } else { - Exception exception = result.UnwrapError().GetException(); + ExceptionDetail exceptionDetail = result.UnwrapError(); + IdentityComparer.AreStringsEqual( + exceptionDetail.FailureType.Name, + theoryData.Result.UnwrapError().FailureType.Name, + context); + + Exception exception = exceptionDetail.GetException(); theoryData.ExpectedException.ProcessException(exception, context); } @@ -104,6 +110,7 @@ public static TheoryData JsonWebTokenHandlerDecryptTo ExpectedException = ExpectedException.SecurityTokenException("IDX10612:"), Result = new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10612), + ValidationFailureType.TokenDecryptionFailed, ExceptionType.SecurityToken, null, null), @@ -115,10 +122,11 @@ public static TheoryData JsonWebTokenHandlerDecryptTo ValidationParameters = new ValidationParameters(), ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), Result = new ExceptionDetail( - new MessageDetail(TokenLogMessages.IDX10000, "jwtToken"), - ExceptionType.ArgumentNull, - null, - null), + new MessageDetail(TokenLogMessages.IDX10000, "jwtToken"), + ValidationFailureType.NullArgument, + ExceptionType.ArgumentNull, + null, + null), }, new TokenDecryptingTheoryData { @@ -128,6 +136,7 @@ public static TheoryData JsonWebTokenHandlerDecryptTo ExpectedException = ExpectedException.ArgumentNullException("IDX10000:"), Result = new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10000, "validationParameters"), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, null), @@ -185,9 +194,10 @@ public static TheoryData JsonWebTokenHandlerDecryptTo LogHelper.MarkAsSecurityArtifact( new JsonWebToken(ReferenceTokens.JWEDirectEncryptionUnsignedInnerJWTWithAdditionalHeaderClaims), JwtTokenUtilities.SafeLogJwtToken)), - ExceptionType.SecurityTokenDecryptionFailed, - null, - null), + ValidationFailureType.TokenDecryptionFailed, + ExceptionType.SecurityTokenDecryptionFailed, + null, + null), } }; } diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs index 30cf258f1f..8a797f941a 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs @@ -32,7 +32,13 @@ public void ReadToken(TokenReadingTheoryData theoryData) } else { - Exception exception = result.UnwrapError().GetException(); + ExceptionDetail exceptionDetail = result.UnwrapError(); + IdentityComparer.AreStringsEqual( + exceptionDetail.FailureType.Name, + theoryData.Result.UnwrapError().FailureType.Name, + context); + + Exception exception = exceptionDetail.GetException(); theoryData.ExpectedException.ProcessException(exception, context); } @@ -71,6 +77,7 @@ public static TheoryData JsonWebTokenHandlerReadTokenTes new MessageDetail( TokenLogMessages.IDX10000, LogHelper.MarkAsNonPII("token")), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, null) @@ -84,6 +91,7 @@ public static TheoryData JsonWebTokenHandlerReadTokenTes new MessageDetail( TokenLogMessages.IDX10000, LogHelper.MarkAsNonPII("token")), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, null) @@ -99,6 +107,7 @@ public static TheoryData JsonWebTokenHandlerReadTokenTes new MessageDetail( LogMessages.IDX14107, LogHelper.MarkAsNonPII("token")), + ValidationFailureType.TokenReadingFailed, ExceptionType.SecurityTokenMalformed, null, new SecurityTokenMalformedException()), diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs index 8a0593daf8..1ecbac1b39 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs @@ -59,7 +59,13 @@ public void ValidateSignature(JsonWebTokenHandlerValidateSignatureTheoryData the } else { - Exception exception = result.UnwrapError().GetException(); + ExceptionDetail exceptionDetail = result.UnwrapError(); + IdentityComparer.AreStringsEqual( + exceptionDetail.FailureType.Name, + theoryData.Result.UnwrapError().FailureType.Name, + context); + + Exception exception = exceptionDetail.GetException(); theoryData.ExpectedException.ProcessException(exception, context); } @@ -81,6 +87,7 @@ public static TheoryData JsonWeb new MessageDetail( TokenLogMessages.IDX10000, "jwtToken"), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, null) @@ -94,6 +101,7 @@ public static TheoryData JsonWeb new MessageDetail( TokenLogMessages.IDX10000, "validationParameters"), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, null) @@ -110,6 +118,7 @@ public static TheoryData JsonWeb new MessageDetail( TokenLogMessages.IDX10000, "fakeParameter"), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, null) @@ -124,6 +133,7 @@ public static TheoryData JsonWeb new MessageDetail( TokenLogMessages.IDX10504, LogHelper.MarkAsSecurityArtifact(unsignedToken, JwtTokenUtilities.SafeLogJwtToken)), + ValidationFailureType.SignatureValidationFailed, ExceptionType.SecurityTokenInvalidSignature, null, null) @@ -193,6 +203,7 @@ public static TheoryData JsonWeb ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException("IDX10500:"), Result = new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10500), + ValidationFailureType.SignatureValidationFailed, ExceptionType.SecurityTokenSignatureKeyNotFound, null, null) @@ -205,6 +216,7 @@ public static TheoryData JsonWeb ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException("IDX10500:"), Result = new ExceptionDetail( new MessageDetail(TokenLogMessages.IDX10500), + ValidationFailureType.SignatureValidationFailed, ExceptionType.SecurityTokenSignatureKeyNotFound, null, null) diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs index 8d42a4b39a..6e5136403d 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs @@ -34,7 +34,13 @@ public void ValidateAlgorithm(AlgorithmTheoryData theoryData) } else { - Exception exception = result.UnwrapError().GetException(); + ExceptionDetail exceptionDetail = result.UnwrapError(); + IdentityComparer.AreStringsEqual( + exceptionDetail.FailureType.Name, + theoryData.Result.UnwrapError().FailureType.Name, + context); + + Exception exception = exceptionDetail.GetException(); theoryData.ExpectedException.ProcessException(exception, context); } @@ -61,6 +67,7 @@ public static TheoryData AlgorithmValidationTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, // StackFrame null) // InnerException @@ -80,6 +87,7 @@ public static TheoryData AlgorithmValidationTestCases new MessageDetail( LogMessages.IDX10696, LogHelper.MarkAsNonPII(SecurityAlgorithms.Sha256)), + ValidationFailureType.AlgorithmValidationFailed, ExceptionType.SecurityTokenInvalidAlgorithm, null, // StackFrame null),// InnerException diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs index fa8c197805..73eb798d4b 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs @@ -42,7 +42,13 @@ public void ValidateAudienceParameters(AudienceValidationTheoryData theoryData) } else { - Exception exception = result.UnwrapError().GetException(); + ExceptionDetail exceptionDetail = result.UnwrapError(); + IdentityComparer.AreStringsEqual( + exceptionDetail.FailureType.Name, + theoryData.Result.UnwrapError().FailureType.Name, + context); + + Exception exception = exceptionDetail.GetException(); theoryData.ExpectedException.ProcessException(exception, context); } @@ -80,6 +86,7 @@ public static TheoryData ValidateAudienceTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, null) @@ -91,6 +98,7 @@ public static TheoryData ValidateAudienceTestCases ExpectedException = ExpectedException.SecurityTokenInvalidAudienceException("IDX10207:"), Result = new ExceptionDetail( new MessageDetail(LogMessages.IDX10207), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null, null) @@ -105,6 +113,7 @@ public static TheoryData ValidateAudienceTestCases new MessageDetail( LogMessages.IDX10206, null), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null, null) @@ -121,6 +130,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII("audience1"), LogHelper.MarkAsNonPII(String.Empty)), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null, null) @@ -137,6 +147,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII("audience1"), LogHelper.MarkAsNonPII(" ")), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null, null) @@ -163,6 +174,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience2)), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null, null) @@ -180,6 +192,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience2Slash)), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null, null) @@ -196,6 +209,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience2Slash), LogHelper.MarkAsNonPII(audience1)), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null, null) @@ -212,6 +226,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience1Slash)), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null) }, @@ -235,6 +250,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(commaAudience1Slash)), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null, null) @@ -259,6 +275,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience1 + "A")), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null, null) @@ -275,6 +292,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(audience1 + "//")), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null, null) @@ -291,6 +309,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1), LogHelper.MarkAsNonPII(commaAudience1 + "//")), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null, null) @@ -307,6 +326,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1Slash), LogHelper.MarkAsNonPII(audience1)), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null, null) @@ -331,6 +351,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience2Slash), LogHelper.MarkAsNonPII(audience1)), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null, null) @@ -347,6 +368,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1Slash), LogHelper.MarkAsNonPII(audience1)), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null, null) @@ -371,6 +393,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1Slash), LogHelper.MarkAsNonPII(commaAudience2)), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null, null) @@ -387,6 +410,7 @@ public static TheoryData ValidateAudienceTestCases LogMessages.IDX10215, LogHelper.MarkAsNonPII(commaAudience1 + "//"), LogHelper.MarkAsNonPII(audience1)), + ValidationFailureType.AudienceValidationFailed, ExceptionType.SecurityTokenInvalidAudience, null, null) diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ExceptionDetailsTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ExceptionDetailsTests.cs index de7bb505d6..c47401adbc 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ExceptionDetailsTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ExceptionDetailsTests.cs @@ -17,6 +17,7 @@ public void ExceptionDetails(ExceptionDetailsTheoryData theoryData) var context = TestUtilities.WriteHeader($"{this}.ExceptionDetails", theoryData); ExceptionDetail exceptionDetail = new ExceptionDetail( new MessageDetail(""), + ValidationFailureType.NullArgument, theoryData.ExceptionType, null); @@ -30,6 +31,7 @@ public void ExceptionDetails_UnknownType_Throws() { ExceptionDetail exceptionDetail = new ExceptionDetail( new MessageDetail(""), + ValidationFailureType.NullArgument, ExceptionType.Unknown, null); diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs index 0eacbeec47..7bf59ab474 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs @@ -42,7 +42,13 @@ public async Task IssuerValidatorAsyncTests(IssuerValidationResultsTheoryData th } else { - Exception exception = result.UnwrapError().GetException(); + ExceptionDetail exceptionDetail = result.UnwrapError(); + IdentityComparer.AreStringsEqual( + exceptionDetail.FailureType.Name, + theoryData.Result.UnwrapError().FailureType.Name, + context); + + Exception exception = exceptionDetail.GetException(); theoryData.ExpectedException.ProcessException(exception, context); } @@ -70,6 +76,7 @@ public static TheoryData IssuerValdationResul LogHelper.MarkAsNonPII(validIssuer), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(null)), LogHelper.MarkAsNonPII(null)), + ValidationFailureType.IssuerValidationFailed, ExceptionType.SecurityTokenInvalidIssuer, null, null), @@ -85,6 +92,7 @@ public static TheoryData IssuerValdationResul new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, null), @@ -100,6 +108,7 @@ public static TheoryData IssuerValdationResul new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, null), @@ -137,6 +146,7 @@ public static TheoryData IssuerValdationResul LogHelper.MarkAsNonPII(issClaim), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validIssuers)), LogHelper.MarkAsNonPII(null)), + ValidationFailureType.IssuerValidationFailed, ExceptionType.SecurityTokenInvalidIssuer, null, null), diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs index 911f086dca..789302b6ad 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs @@ -34,7 +34,13 @@ public void ValidateLifetime(ValidateLifetimeTheoryData theoryData) } else { - Exception exception = result.UnwrapError().GetException(); + ExceptionDetail exceptionDetail = result.UnwrapError(); + IdentityComparer.AreStringsEqual( + exceptionDetail.FailureType.Name, + theoryData.Result.UnwrapError().FailureType.Name, + context); + + Exception exception = exceptionDetail.GetException(); theoryData.ExpectedException.ProcessException(exception, context); } @@ -94,8 +100,8 @@ public static TheoryData ValidateLifetimeTestCases ValidationParameters = null, Result = new ExceptionDetail( new MessageDetail(LogMessages.IDX10000, "validationParameters"), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, - null, null), }, new ValidateLifetimeTheoryData("Invalid_ExpiresIsNull") @@ -105,8 +111,8 @@ public static TheoryData ValidateLifetimeTestCases ValidationParameters = new ValidationParameters(), Result = new ExceptionDetail( new MessageDetail(LogMessages.IDX10225, "null"), + ValidationFailureType.LifetimeValidationFailed, ExceptionType.SecurityTokenNoExpiration, - null, null), }, new ValidateLifetimeTheoryData("Invalid_NotBeforeIsAfterExpires") @@ -120,8 +126,8 @@ public static TheoryData ValidateLifetimeTestCases LogMessages.IDX10224, LogHelper.MarkAsNonPII(oneHourFromNow), LogHelper.MarkAsNonPII(oneHourAgo)), + ValidationFailureType.LifetimeValidationFailed, ExceptionType.SecurityTokenInvalidLifetime, - null, null), }, new ValidateLifetimeTheoryData("Invalid_NotYetValid") @@ -135,8 +141,8 @@ public static TheoryData ValidateLifetimeTestCases LogMessages.IDX10222, LogHelper.MarkAsNonPII(oneHourFromNow), LogHelper.MarkAsNonPII(now)), + ValidationFailureType.LifetimeValidationFailed, ExceptionType.SecurityTokenNotYetValid, - null, null), }, new ValidateLifetimeTheoryData("Invalid_Expired") @@ -150,8 +156,8 @@ public static TheoryData ValidateLifetimeTestCases LogMessages.IDX10223, LogHelper.MarkAsNonPII(oneHourAgo), LogHelper.MarkAsNonPII(now)), + ValidationFailureType.LifetimeValidationFailed, ExceptionType.SecurityTokenExpired, - null, null), }, new ValidateLifetimeTheoryData("Invalid_NotYetValid_SkewForward") @@ -165,8 +171,8 @@ public static TheoryData ValidateLifetimeTestCases LogMessages.IDX10222, LogHelper.MarkAsNonPII(sixMinutesFromNow), LogHelper.MarkAsNonPII(now)), + ValidationFailureType.LifetimeValidationFailed, ExceptionType.SecurityTokenNotYetValid, - null, null), }, new ValidateLifetimeTheoryData("Invalid_Expired_SkewBackward") @@ -180,6 +186,7 @@ public static TheoryData ValidateLifetimeTestCases LogMessages.IDX10223, LogHelper.MarkAsNonPII(sixMinutesAgo), LogHelper.MarkAsNonPII(now)), + ValidationFailureType.LifetimeValidationFailed, ExceptionType.SecurityTokenExpired, null), } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs index 7e44d250d8..1f1acf8af6 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs @@ -34,7 +34,13 @@ public void ValidateTokenReplay(TokenReplayTheoryData theoryData) } else { - Exception exception = result.UnwrapError().GetException(); + ExceptionDetail exceptionDetail = result.UnwrapError(); + IdentityComparer.AreStringsEqual( + exceptionDetail.FailureType.Name, + theoryData.Result.UnwrapError().FailureType.Name, + context); + + Exception exception = exceptionDetail.GetException(); theoryData.ExpectedException.ProcessException(exception, context); } @@ -84,6 +90,7 @@ public static TheoryData TokenReplayValidationTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, null), @@ -99,6 +106,7 @@ public static TheoryData TokenReplayValidationTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, null), @@ -114,6 +122,7 @@ public static TheoryData TokenReplayValidationTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, null), @@ -136,6 +145,7 @@ public static TheoryData TokenReplayValidationTestCases new MessageDetail( LogMessages.IDX10227, LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), + ValidationFailureType.TokenReplayValidationFailed, ExceptionType.SecurityTokenReplayDetected, null, null), @@ -158,6 +168,7 @@ public static TheoryData TokenReplayValidationTestCases new MessageDetail( LogMessages.IDX10228, LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), + ValidationFailureType.TokenReplayValidationFailed, ExceptionType.SecurityTokenReplayDetected, null, null), @@ -180,6 +191,7 @@ public static TheoryData TokenReplayValidationTestCases new MessageDetail( LogMessages.IDX10229, LogHelper.MarkAsUnsafeSecurityArtifact("token", t => t.ToString())), + ValidationFailureType.TokenReplayValidationFailed, ExceptionType.SecurityTokenReplayDetected, null, null), diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs index fd62fd3653..e2b3eaaa1d 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs @@ -35,7 +35,13 @@ public void SecurityKey(SigningKeyValidationTheoryData theoryData) } else { - Exception exception = result.UnwrapError().GetException(); + ExceptionDetail exceptionDetail = result.UnwrapError(); + IdentityComparer.AreStringsEqual( + exceptionDetail.FailureType.Name, + theoryData.Result.UnwrapError().FailureType.Name, + context); + + Exception exception = exceptionDetail.GetException(); theoryData.ExpectedException.ProcessException(exception, context); } @@ -69,6 +75,7 @@ public static TheoryData SigningKeyValidationTes ValidationParameters = new ValidationParameters(), Result = new ExceptionDetail( new MessageDetail(LogMessages.IDX10253), + ValidationFailureType.SigningKeyValidationFailed, ExceptionType.ArgumentNull, null, null), @@ -84,6 +91,7 @@ public static TheoryData SigningKeyValidationTes new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, null), @@ -99,6 +107,7 @@ public static TheoryData SigningKeyValidationTes new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, null), @@ -115,6 +124,7 @@ public static TheoryData SigningKeyValidationTes LogMessages.IDX10249, LogHelper.MarkAsNonPII(utcExpired), LogHelper.MarkAsNonPII(utcNow)), + ValidationFailureType.SigningKeyValidationFailed, ExceptionType.SecurityTokenInvalidSigningKey, null, null), @@ -131,6 +141,7 @@ public static TheoryData SigningKeyValidationTes LogMessages.IDX10248, LogHelper.MarkAsNonPII(utcNotYetValid), LogHelper.MarkAsNonPII(utcNow)), + ValidationFailureType.SigningKeyValidationFailed, ExceptionType.SecurityTokenInvalidSigningKey, null, null), @@ -144,6 +155,7 @@ public static TheoryData SigningKeyValidationTes ValidationParameters = new ValidationParameters (), Result = new ExceptionDetail( new MessageDetail(LogMessages.IDX10253), + ValidationFailureType.SigningKeyValidationFailed, ExceptionType.ArgumentNull, null, null), diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs index a60ff76d9e..475000d14c 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs @@ -42,7 +42,13 @@ public void ValidateTokenType(TokenTypeTheoryData theoryData) } else { - Exception exception = result.UnwrapError().GetException(); + ExceptionDetail exceptionDetail = result.UnwrapError(); + IdentityComparer.AreStringsEqual( + exceptionDetail.FailureType.Name, + theoryData.Result.UnwrapError().FailureType.Name, + context); + + Exception exception = exceptionDetail.GetException(); theoryData.ExpectedException.ProcessException(exception, context); } @@ -79,6 +85,7 @@ public static TheoryData TokenTypeValidationTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("securityToken")), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, null) @@ -94,6 +101,7 @@ public static TheoryData TokenTypeValidationTestCases new MessageDetail( LogMessages.IDX10000, LogHelper.MarkAsNonPII("validationParameters")), + ValidationFailureType.NullArgument, ExceptionType.ArgumentNull, null, null) @@ -110,6 +118,7 @@ public static TheoryData TokenTypeValidationTestCases new MessageDetail( LogMessages.IDX10256, LogHelper.MarkAsNonPII("type")), + ValidationFailureType.TokenTypeValidationFailed, ExceptionType.SecurityTokenInvalidType, null, null) @@ -126,6 +135,7 @@ public static TheoryData TokenTypeValidationTestCases new MessageDetail( LogMessages.IDX10256, LogHelper.MarkAsNonPII("type")), + ValidationFailureType.TokenTypeValidationFailed, ExceptionType.SecurityTokenInvalidType, null, null) @@ -143,6 +153,7 @@ public static TheoryData TokenTypeValidationTestCases LogMessages.IDX10257, LogHelper.MarkAsNonPII("type"), LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validTypesNoJwt))), + ValidationFailureType.TokenTypeValidationFailed, ExceptionType.SecurityTokenInvalidType, null, null) From 79885683bfb657f523ad044c1677ac96eafda229 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Tue, 27 Aug 2024 15:12:26 +0100 Subject: [PATCH 29/32] Update src/Microsoft.IdentityModel.Abstractions/Result.cs Co-authored-by: Keegan Caruso --- src/Microsoft.IdentityModel.Abstractions/Result.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.IdentityModel.Abstractions/Result.cs b/src/Microsoft.IdentityModel.Abstractions/Result.cs index b4fe1f5c6f..721f54d39e 100644 --- a/src/Microsoft.IdentityModel.Abstractions/Result.cs +++ b/src/Microsoft.IdentityModel.Abstractions/Result.cs @@ -61,7 +61,7 @@ public Result(TError error) /// /// Gets a value indicating whether the result is successful. /// - readonly public bool IsSuccess { get; } + public readonly bool IsSuccess { get; } /// /// Unwraps the result. From fb2c6eec45434b1ab1d76a1e660020a996303eba Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Tue, 27 Aug 2024 17:54:12 +0100 Subject: [PATCH 30/32] Moved Result to Tokens project, made it internal. Reverted TargetFrameworks change to LoggingExtensions --- .../JsonWebTokenHandler.DecryptToken.cs | 1 - .../JsonWebTokenHandler.ReadToken.cs | 1 - .../JsonWebTokenHandler.ValidateSignature.cs | 1 - .../JsonWebTokenHandler.ValidateToken.Internal.cs | 1 - .../JwtTokenUtilities.DecryptTokenResult.cs | 1 - .../Microsoft.IdentityModel.LoggingExtensions.csproj | 2 +- src/Microsoft.IdentityModel.Tokens/Delegates.cs | 1 - .../Validation/Results}/Result.cs | 4 ++-- .../Validation/ValidationParameters.cs | 1 - .../Validation/Validators.Algorithm.cs | 1 - .../Validation/Validators.Issuer.cs | 1 - .../Validation/Validators.IssuerSigningKey.cs | 1 - .../Validation/Validators.TokenReplay.cs | 1 - .../Validation/Validators.TokenType.cs | 1 - 14 files changed, 3 insertions(+), 15 deletions(-) rename src/{Microsoft.IdentityModel.Abstractions => Microsoft.IdentityModel.Tokens/Validation/Results}/Result.cs (97%) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs index eed4e39e5e..5e12c33897 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.DecryptToken.cs @@ -6,7 +6,6 @@ using System.Diagnostics; using System.Linq; using System.Text; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Tokens; using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages; diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs index ac2ea435d1..a37d327fcd 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ReadToken.cs @@ -3,7 +3,6 @@ using System; using System.Diagnostics; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Tokens; namespace Microsoft.IdentityModel.JsonWebTokens diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs index 62df40a484..65c48fdfaa 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateSignature.cs @@ -6,7 +6,6 @@ using System.Diagnostics; using System.Linq; using System.Text; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Tokens; using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages; diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs index 9ce61dc2e5..6986155744 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.Internal.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Logging; using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages; diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs index bd30f17651..330f18b3f3 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs @@ -5,7 +5,6 @@ using System.Diagnostics; using System.Text; using Microsoft.IdentityModel.Tokens; -using Microsoft.IdentityModel.Abstractions; using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages; namespace Microsoft.IdentityModel.JsonWebTokens diff --git a/src/Microsoft.IdentityModel.LoggingExtensions/Microsoft.IdentityModel.LoggingExtensions.csproj b/src/Microsoft.IdentityModel.LoggingExtensions/Microsoft.IdentityModel.LoggingExtensions.csproj index 596fad207c..f91d554aec 100644 --- a/src/Microsoft.IdentityModel.LoggingExtensions/Microsoft.IdentityModel.LoggingExtensions.csproj +++ b/src/Microsoft.IdentityModel.LoggingExtensions/Microsoft.IdentityModel.LoggingExtensions.csproj @@ -8,7 +8,7 @@ true Microsoft.IdentityModel.LoggingExtensions .NET;Windows;Authentication;Identity;Extensions;Logging - netstandard2.0;net8.0 + netstandard2.0 enable diff --git a/src/Microsoft.IdentityModel.Tokens/Delegates.cs b/src/Microsoft.IdentityModel.Tokens/Delegates.cs index 485727f5c8..5bfcb566f8 100644 --- a/src/Microsoft.IdentityModel.Tokens/Delegates.cs +++ b/src/Microsoft.IdentityModel.Tokens/Delegates.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Microsoft.IdentityModel.Abstractions; namespace Microsoft.IdentityModel.Tokens { diff --git a/src/Microsoft.IdentityModel.Abstractions/Result.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Result.cs similarity index 97% rename from src/Microsoft.IdentityModel.Abstractions/Result.cs rename to src/Microsoft.IdentityModel.Tokens/Validation/Results/Result.cs index 721f54d39e..9bf349fa18 100644 --- a/src/Microsoft.IdentityModel.Abstractions/Result.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/Result.cs @@ -4,14 +4,14 @@ using System; #nullable enable -namespace Microsoft.IdentityModel.Abstractions +namespace Microsoft.IdentityModel.Tokens { /// /// Represents a result that can be either successful or unsuccessful. /// /// /// - public readonly struct Result : IEquatable> + internal readonly struct Result : IEquatable> { readonly TResult? _result; readonly TError? _error; diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs b/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs index 5e612cdd82..d05477bcab 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/ValidationParameters.cs @@ -6,7 +6,6 @@ using System.ComponentModel; using System.Security.Claims; using System.Threading; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; namespace Microsoft.IdentityModel.Tokens diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs index 15fd8baf82..ac7330e331 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Algorithm.cs @@ -4,7 +4,6 @@ using System; using System.Diagnostics; using System.Linq; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; #nullable enable diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs index cf8e5f5894..0e2e32ed73 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs @@ -4,7 +4,6 @@ using System.Diagnostics; using System.Threading; using System.Threading.Tasks; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; namespace Microsoft.IdentityModel.Tokens diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs index 6cabad2b25..f618ec6756 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.IssuerSigningKey.cs @@ -4,7 +4,6 @@ using System; using System.Diagnostics; using System.Security.Cryptography.X509Certificates; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; #nullable enable diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs index f110c8eb02..a49cd85491 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenReplay.cs @@ -3,7 +3,6 @@ using System; using System.Diagnostics; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; namespace Microsoft.IdentityModel.Tokens diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs index b6ce0a9d28..8982e9ed9f 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Validators.TokenType.cs @@ -4,7 +4,6 @@ using System; using System.Diagnostics; using System.Linq; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; #nullable enable From c84d3480c05620d2967263f02c0a2e66947c9bad Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Tue, 27 Aug 2024 17:59:34 +0100 Subject: [PATCH 31/32] Addressed PR feedback around argument null exceptions --- .../Validation/Results/ValidationResult.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs index f0f05fdeb9..421c4a1a86 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidationResult.cs @@ -27,9 +27,9 @@ internal ValidationResult( TokenHandler tokenHandler, ValidationParameters validationParameters) { - TokenHandler = tokenHandler ?? throw new ArgumentNullException("TokenHandler cannot be null."); - SecurityToken = securityToken ?? throw new ArgumentNullException("SecurityToken cannot be null."); - ValidationParameters = validationParameters ?? throw new ArgumentNullException("ValidationParameters cannot be null."); ; + TokenHandler = tokenHandler ?? throw new ArgumentNullException(nameof(tokenHandler)); + SecurityToken = securityToken ?? throw new ArgumentNullException(nameof(securityToken)); + ValidationParameters = validationParameters ?? throw new ArgumentNullException(nameof(validationParameters)); } /// From 4ddef570dbd966a2475987626005bf39d5cb9aa8 Mon Sep 17 00:00:00 2001 From: Ignacio Inglese Date: Wed, 28 Aug 2024 13:00:50 +0100 Subject: [PATCH 32/32] Addressed PR comments. Removed unused imports. Increased epsilon for datetime comparison in tests. --- .../ValidateTokenAsyncTests.cs | 1 - .../JsonWebTokenHandler.ReadTokenTests.cs | 1 - .../JsonWebTokenHandler.ValidateSignatureTests.cs | 1 - test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs | 7 +++---- .../Validation/AlgorithmValidationResultTests.cs | 1 - .../Validation/AudienceValidationResultTests.cs | 1 - .../Validation/IssuerValidationResultTests.cs | 1 - .../Validation/LifetimeValidationResultTests.cs | 1 - .../Validation/ReplayValidationResultTests.cs | 1 - .../Validation/SigningKeyValidationResultTests.cs | 1 - .../Validation/TokenTypeValidationResultTests.cs | 1 - 11 files changed, 3 insertions(+), 14 deletions(-) diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncTests.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncTests.cs index aa366e4019..b174a691dd 100644 --- a/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncTests.cs +++ b/benchmark/Microsoft.IdentityModel.Benchmarks/ValidateTokenAsyncTests.cs @@ -9,7 +9,6 @@ using System.Threading.Tasks; using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs index 8a797f941a..01912a41ed 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ReadTokenTests.cs @@ -3,7 +3,6 @@ using System; using System.IdentityModel.Tokens.Jwt.Tests; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.TestUtils; using Microsoft.IdentityModel.Tokens; diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs index 1ecbac1b39..b2297b6527 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateSignatureTests.cs @@ -3,7 +3,6 @@ using System; using System.IdentityModel.Tokens.Jwt.Tests; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.TestUtils; diff --git a/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs b/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs index 3eae6e2e32..614f5f613f 100644 --- a/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs +++ b/test/Microsoft.IdentityModel.TestUtils/IdentityComparer.cs @@ -20,7 +20,6 @@ using System.Security.Cryptography.X509Certificates; using System.Text.Json; using System.Text.RegularExpressions; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Protocols.OpenIdConnect; @@ -1276,19 +1275,19 @@ internal static bool AreValidatedSigningKeyLifetimesEqual(ValidatedSigningKeyLif AreDateTimesEqualWithEpsilon( validatedSigningKeyLifetime1.ValidFrom, validatedSigningKeyLifetime2.ValidFrom, - 1, + 3, localContext); AreDateTimesEqualWithEpsilon( validatedSigningKeyLifetime1.ValidTo, validatedSigningKeyLifetime2.ValidTo, - 1, + 3, localContext); AreDateTimesEqualWithEpsilon( validatedSigningKeyLifetime1.ValidationTime, validatedSigningKeyLifetime2.ValidationTime, - 1, + 3, localContext); return context.Merge(localContext); diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs index 6e5136403d..a5c0d9fa35 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AlgorithmValidationResultTests.cs @@ -4,7 +4,6 @@ using Microsoft.IdentityModel.TestUtils; using Microsoft.IdentityModel.Logging; using Xunit; -using Microsoft.IdentityModel.Abstractions; using System; namespace Microsoft.IdentityModel.Tokens.Validation.Tests diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs index 73eb798d4b..a97fcdbea5 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/AudienceValidationResultTests.cs @@ -8,7 +8,6 @@ using Microsoft.IdentityModel.Tokens.Json.Tests; using Xunit; using System.Collections.Generic; -using Microsoft.IdentityModel.Abstractions; namespace Microsoft.IdentityModel.Tokens.Validation.Tests { diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs index a8ef23d6bd..d4157e12a0 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/IssuerValidationResultTests.cs @@ -4,7 +4,6 @@ using System; using System.Threading; using System.Threading.Tasks; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.TestUtils; diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs index 789302b6ad..386c58182d 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/LifetimeValidationResultTests.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.TestUtils; using Xunit; diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs index 1f1acf8af6..3e3dcfe78b 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/ReplayValidationResultTests.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.TestUtils; using Xunit; diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs index e2b3eaaa1d..b93b6daf74 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/SigningKeyValidationResultTests.cs @@ -3,7 +3,6 @@ using System; using System.IdentityModel.Tokens.Jwt; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.TestUtils; using Xunit; diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs index 475000d14c..10d59be7d4 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Validation/TokenTypeValidationResultTests.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.TestUtils; using Microsoft.IdentityModel.Tokens.Json.Tests; using Microsoft.IdentityModel.JsonWebTokens;