Skip to content

Commit 3de9384

Browse files
brentschmaltzHP712
andauthored
Remove experimental code from TokenValidationResult (#3259)
* remove experimental code from TokenValidationResult * move all experimental code into partial classes --------- Co-authored-by: id4s <[email protected]>
1 parent ec9d65b commit 3de9384

18 files changed

+486
-430
lines changed

src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ internal async ValueTask<TokenValidationResult> ValidateTokenPayloadAsync(
598598
}
599599

600600
string tokenType = Validators.ValidateTokenType(jsonWebToken.Typ, jsonWebToken, validationParameters);
601-
return new TokenValidationResult(jsonWebToken, this, validationParameters.Clone(), issuer, null)
601+
return new TokenValidationResult(jsonWebToken, this, validationParameters.Clone(), issuer)
602602
{
603603
IsValid = true,
604604
TokenType = tokenType

src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.DecryptTokenResult.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33

44
using System;
55
using System.Text;
6+
using Microsoft.IdentityModel.Logging;
67
using Microsoft.IdentityModel.Tokens;
78
using Microsoft.IdentityModel.Tokens.Experimental;
9+
using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages;
810

911
namespace Microsoft.IdentityModel.JsonWebTokens
1012
{
@@ -127,5 +129,44 @@ internal static ValidationResult<string, ValidationError> DecryptJwtToken(
127129
ex);
128130
}
129131
}
132+
133+
private static ValidationError GetDecryptionError(
134+
JwtTokenDecryptionParameters decryptionParameters,
135+
bool algorithmNotSupportedByCryptoProvider,
136+
StringBuilder exceptionStrings,
137+
StringBuilder keysAttempted,
138+
#pragma warning disable CA1801 // Review unused parameters
139+
CallContext callContext)
140+
#pragma warning restore CA1801 // Review unused parameters
141+
{
142+
if (keysAttempted is not null)
143+
return new ValidationError(
144+
new MessageDetail(
145+
TokenLogMessages.IDX10603,
146+
LogHelper.MarkAsNonPII(keysAttempted.ToString()),
147+
exceptionStrings?.ToString() ?? string.Empty,
148+
LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken)),
149+
ValidationFailureType.TokenDecryptionFailed,
150+
typeof(SecurityTokenDecryptionFailedException),
151+
ValidationError.GetCurrentStackFrame());
152+
else if (algorithmNotSupportedByCryptoProvider)
153+
return new ValidationError(
154+
new MessageDetail(
155+
TokenLogMessages.IDX10619,
156+
LogHelper.MarkAsNonPII(decryptionParameters.Alg),
157+
LogHelper.MarkAsNonPII(decryptionParameters.Enc)),
158+
ValidationFailureType.TokenDecryptionFailed,
159+
typeof(SecurityTokenDecryptionFailedException),
160+
ValidationError.GetCurrentStackFrame());
161+
else
162+
return new ValidationError(
163+
new MessageDetail(
164+
TokenLogMessages.IDX10609,
165+
LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken)),
166+
ValidationFailureType.TokenDecryptionFailed,
167+
typeof(SecurityTokenDecryptionFailedException),
168+
ValidationError.GetCurrentStackFrame());
169+
}
170+
130171
}
131172
}

src/Microsoft.IdentityModel.JsonWebTokens/JwtTokenUtilities.cs

Lines changed: 33 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
using Microsoft.IdentityModel.Abstractions;
1313
using Microsoft.IdentityModel.Logging;
1414
using Microsoft.IdentityModel.Tokens;
15-
using Microsoft.IdentityModel.Tokens.Experimental;
1615
using Microsoft.IdentityModel.Tokens.Json;
1716

1817
using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages;
@@ -284,7 +283,10 @@ internal static string DecryptJwtToken(
284283
if (!cryptoProviderFactory.IsSupportedAlgorithm(decryptionParameters.Enc, key))
285284
{
286285
if (LogHelper.IsEnabled(EventLogLevel.Warning))
287-
LogHelper.LogWarning(TokenLogMessages.IDX10611, LogHelper.MarkAsNonPII(decryptionParameters.Enc), LogHelper.MarkAsNonPII(key.KeyId));
286+
LogHelper.LogWarning(
287+
TokenLogMessages.IDX10611,
288+
LogHelper.MarkAsNonPII(decryptionParameters.Enc),
289+
LogHelper.MarkAsNonPII(key.KeyId));
288290

289291
algorithmNotSupportedByCryptoProvider = true;
290292
continue;
@@ -313,17 +315,7 @@ internal static string DecryptJwtToken(
313315
(keysAttempted ??= new StringBuilder()).AppendLine(key.KeyId);
314316
}
315317

316-
if (!decryptionSucceeded)
317-
{
318-
ValidationError validationError = GetDecryptionError(
319-
decryptionParameters,
320-
algorithmNotSupportedByCryptoProvider,
321-
exceptionStrings,
322-
keysAttempted,
323-
null);
324-
325-
throw LogHelper.LogExceptionMessage(validationError.GetException());
326-
}
318+
ValidateDecryption(decryptionParameters, decryptionSucceeded, algorithmNotSupportedByCryptoProvider, exceptionStrings, keysAttempted);
327319

328320
try
329321
{
@@ -334,46 +326,38 @@ internal static string DecryptJwtToken(
334326
}
335327
catch (Exception ex)
336328
{
337-
throw LogHelper.LogExceptionMessage(new SecurityTokenDecompressionFailedException(GetIDX10679LogMessage(zipAlgorithm), ex));
329+
throw LogHelper.LogExceptionMessage(
330+
new SecurityTokenDecompressionFailedException(
331+
GetIDX10679LogMessage(zipAlgorithm),
332+
ex));
338333
}
339334
}
340335

341-
private static ValidationError GetDecryptionError(
342-
JwtTokenDecryptionParameters decryptionParameters,
343-
bool algorithmNotSupportedByCryptoProvider,
344-
StringBuilder exceptionStrings,
345-
StringBuilder keysAttempted,
346-
#pragma warning disable CA1801 // Review unused parameters
347-
CallContext callContext)
348-
#pragma warning restore CA1801 // Review unused parameters
336+
private static void ValidateDecryption(JwtTokenDecryptionParameters decryptionParameters, bool decryptionSucceeded, bool algorithmNotSupportedByCryptoProvider, StringBuilder exceptionStrings, StringBuilder keysAttempted)
349337
{
350-
if (keysAttempted is not null)
351-
return new ValidationError(
352-
new MessageDetail(
353-
TokenLogMessages.IDX10603,
354-
LogHelper.MarkAsNonPII(keysAttempted.ToString()),
355-
exceptionStrings?.ToString() ?? string.Empty,
356-
LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken)),
357-
ValidationFailureType.TokenDecryptionFailed,
358-
typeof(SecurityTokenDecryptionFailedException),
359-
ValidationError.GetCurrentStackFrame());
360-
else if (algorithmNotSupportedByCryptoProvider)
361-
return new ValidationError(
362-
new MessageDetail(
363-
TokenLogMessages.IDX10619,
364-
LogHelper.MarkAsNonPII(decryptionParameters.Alg),
365-
LogHelper.MarkAsNonPII(decryptionParameters.Enc)),
366-
ValidationFailureType.TokenDecryptionFailed,
367-
typeof(SecurityTokenDecryptionFailedException),
368-
ValidationError.GetCurrentStackFrame());
369-
else
370-
return new ValidationError(
371-
new MessageDetail(
372-
TokenLogMessages.IDX10609,
373-
LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken)),
374-
ValidationFailureType.TokenDecryptionFailed,
375-
typeof(SecurityTokenDecryptionFailedException),
376-
ValidationError.GetCurrentStackFrame());
338+
if (!decryptionSucceeded && keysAttempted is not null)
339+
throw LogHelper.LogExceptionMessage(
340+
new SecurityTokenDecryptionFailedException(
341+
LogHelper.FormatInvariant(
342+
TokenLogMessages.IDX10603,
343+
LogHelper.MarkAsNonPII(keysAttempted.ToString()),
344+
(object)exceptionStrings ?? string.Empty,
345+
LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken))));
346+
347+
if (!decryptionSucceeded && algorithmNotSupportedByCryptoProvider)
348+
throw LogHelper.LogExceptionMessage(
349+
new SecurityTokenDecryptionFailedException(
350+
LogHelper.FormatInvariant(
351+
TokenLogMessages.IDX10619,
352+
LogHelper.MarkAsNonPII(decryptionParameters.Alg),
353+
LogHelper.MarkAsNonPII(decryptionParameters.Enc))));
354+
355+
if (!decryptionSucceeded)
356+
throw LogHelper.LogExceptionMessage(
357+
new SecurityTokenDecryptionFailedException(
358+
LogHelper.FormatInvariant(
359+
TokenLogMessages.IDX10609,
360+
LogHelper.MarkAsSecurityArtifact(decryptionParameters.EncodedToken, SafeLogJwtToken))));
377361
}
378362

379363
private static byte[] DecryptToken(CryptoProviderFactory cryptoProviderFactory, SecurityKey key, string encAlg, byte[] ciphertext, byte[] headerAscii, byte[] initializationVector, byte[] authenticationTag)
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+

2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// Licensed under the MIT License.
4+
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using Microsoft.IdentityModel.Tokens.Experimental;
8+
using Microsoft.IdentityModel.Xml;
9+
10+
namespace Microsoft.IdentityModel.Tokens.Saml
11+
{
12+
/// <summary>
13+
/// A class which contains useful methods for processing saml tokens.
14+
/// </summary>
15+
internal partial class SamlTokenUtilities
16+
{
17+
/// <summary>
18+
/// Returns a <see cref="SecurityKey"/> to use when validating the signature of a token.
19+
/// </summary>
20+
/// <param name="tokenKeyInfo">The <see cref="KeyInfo"/> field of the token being validated</param>
21+
/// <param name="validationParameters">The <see cref="ValidationParameters"/> to be used for validating the token.</param>
22+
/// <returns>Returns a <see cref="SecurityKey"/> to use for signature validation.</returns>
23+
/// <remarks>If key fails to resolve, then null is returned</remarks>
24+
internal static SecurityKey ResolveTokenSigningKey(KeyInfo tokenKeyInfo, ValidationParameters validationParameters)
25+
{
26+
if (tokenKeyInfo is null || validationParameters.IssuerSigningKeys is null)
27+
return null;
28+
29+
for (int i = 0; i < validationParameters.IssuerSigningKeys.Count; i++)
30+
{
31+
if (tokenKeyInfo.MatchesKey(validationParameters.IssuerSigningKeys[i]))
32+
return validationParameters.IssuerSigningKeys[i];
33+
}
34+
35+
return null;
36+
}
37+
38+
/// <summary>
39+
/// Fetches current configuration from the ConfigurationManager of <paramref name="validationParameters"/>
40+
/// and populates ValidIssuers and IssuerSigningKeys.
41+
/// </summary>
42+
/// <param name="validationParameters"> the token validation parameters to update.</param>
43+
/// <param name="cancellationToken"></param>
44+
/// <returns> New ValidationParameters with ValidIssuers and IssuerSigningKeys updated.</returns>
45+
internal static async Task<ValidationParameters> PopulateValidationParametersWithCurrentConfigurationAsync(
46+
ValidationParameters validationParameters,
47+
CancellationToken cancellationToken)
48+
{
49+
if (validationParameters.ConfigurationManager == null)
50+
{
51+
return validationParameters;
52+
}
53+
54+
var currentConfiguration = await validationParameters.ConfigurationManager.GetBaseConfigurationAsync(cancellationToken).ConfigureAwait(false);
55+
var validationParametersCloned = validationParameters.Clone();
56+
57+
validationParametersCloned.ValidIssuers.Add(currentConfiguration.Issuer);
58+
59+
foreach (SecurityKey key in currentConfiguration.SigningKeys)
60+
{
61+
validationParametersCloned.IssuerSigningKeys.Add(key);
62+
}
63+
64+
return validationParametersCloned;
65+
}
66+
}
67+
}

src/Microsoft.IdentityModel.Tokens.Saml/Saml/SamlTokenUtilities.cs

Lines changed: 1 addition & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,13 @@
1212
using System.Threading.Tasks;
1313
using Microsoft.IdentityModel.Logging;
1414
using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages;
15-
using Microsoft.IdentityModel.Tokens.Experimental;
1615

1716
namespace Microsoft.IdentityModel.Tokens.Saml
1817
{
1918
/// <summary>
2019
/// A class which contains useful methods for processing saml tokens.
2120
/// </summary>
22-
internal class SamlTokenUtilities
21+
internal partial class SamlTokenUtilities
2322
{
2423
/// <summary>
2524
/// Returns a <see cref="SecurityKey"/> to use when validating the signature of a token.
@@ -48,29 +47,6 @@ internal static SecurityKey ResolveTokenSigningKey(KeyInfo tokenKeyInfo, TokenVa
4847
return null;
4948
}
5049

51-
/// <summary>
52-
/// Returns a <see cref="SecurityKey"/> to use when validating the signature of a token.
53-
/// </summary>
54-
/// <param name="tokenKeyInfo">The <see cref="KeyInfo"/> field of the token being validated</param>
55-
/// <param name="validationParameters">The <see cref="ValidationParameters"/> to be used for validating the token.</param>
56-
/// <returns>Returns a <see cref="SecurityKey"/> to use for signature validation.</returns>
57-
/// <remarks>If key fails to resolve, then null is returned</remarks>
58-
internal static SecurityKey ResolveTokenSigningKey(KeyInfo tokenKeyInfo, ValidationParameters validationParameters)
59-
{
60-
if (tokenKeyInfo is null || validationParameters.IssuerSigningKeys is null)
61-
return null;
62-
63-
for (int i = 0; i < validationParameters.IssuerSigningKeys.Count; i++)
64-
{
65-
if (tokenKeyInfo.MatchesKey(validationParameters.IssuerSigningKeys[i]))
66-
return validationParameters.IssuerSigningKeys[i];
67-
}
68-
69-
return null;
70-
}
71-
72-
73-
7450
/// <summary>
7551
/// Creates <see cref="Claim"/>'s from <paramref name="claimsCollection"/>.
7652
/// </summary>
@@ -176,36 +152,6 @@ internal static async Task<TokenValidationParameters> PopulateValidationParamete
176152
validationParametersCloned.ValidIssuers = (validationParametersCloned.ValidIssuers == null ? issuers : validationParametersCloned.ValidIssuers.Concat(issuers));
177153
validationParametersCloned.IssuerSigningKeys = (validationParametersCloned.IssuerSigningKeys == null ? currentConfiguration.SigningKeys : validationParametersCloned.IssuerSigningKeys.Concat(currentConfiguration.SigningKeys));
178154
return validationParametersCloned;
179-
180-
}
181-
182-
/// <summary>
183-
/// Fetches current configuration from the ConfigurationManager of <paramref name="validationParameters"/>
184-
/// and populates ValidIssuers and IssuerSigningKeys.
185-
/// </summary>
186-
/// <param name="validationParameters"> the token validation parameters to update.</param>
187-
/// <param name="cancellationToken"></param>
188-
/// <returns> New ValidationParameters with ValidIssuers and IssuerSigningKeys updated.</returns>
189-
internal static async Task<ValidationParameters> PopulateValidationParametersWithCurrentConfigurationAsync(
190-
ValidationParameters validationParameters,
191-
CancellationToken cancellationToken)
192-
{
193-
if (validationParameters.ConfigurationManager == null)
194-
{
195-
return validationParameters;
196-
}
197-
198-
var currentConfiguration = await validationParameters.ConfigurationManager.GetBaseConfigurationAsync(cancellationToken).ConfigureAwait(false);
199-
var validationParametersCloned = validationParameters.Clone();
200-
201-
validationParametersCloned.ValidIssuers.Add(currentConfiguration.Issuer);
202-
203-
foreach (SecurityKey key in currentConfiguration.SigningKeys)
204-
{
205-
validationParametersCloned.IssuerSigningKeys.Add(key);
206-
}
207-
208-
return validationParametersCloned;
209155
}
210156
}
211157
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Diagnostics;
6+
using Microsoft.IdentityModel.Tokens.Experimental;
7+
8+
#if !NET8_0_OR_GREATER
9+
using System.Text;
10+
#endif
11+
12+
namespace Microsoft.IdentityModel.Tokens
13+
{
14+
/// <summary>
15+
/// Represents a security token exception.
16+
/// </summary>
17+
public partial class SecurityTokenException : Exception
18+
{
19+
[NonSerialized]
20+
private string _stackTrace;
21+
22+
[NonSerialized]
23+
private ValidationError _validationError;
24+
25+
/// <summary>
26+
/// Sets the <see cref="ValidationError"/> that caused the exception.
27+
/// </summary>
28+
/// <param name="validationError"></param>
29+
internal void SetValidationError(ValidationError validationError)
30+
{
31+
_validationError = validationError;
32+
}
33+
34+
/// <summary>
35+
/// Gets the stack trace that is captured when the exception is created.
36+
/// </summary>
37+
public override string StackTrace
38+
{
39+
get
40+
{
41+
if (_stackTrace == null)
42+
{
43+
if (_validationError == null)
44+
return base.StackTrace;
45+
#if NET8_0_OR_GREATER
46+
_stackTrace = new StackTrace(_validationError.StackFrames).ToString();
47+
#else
48+
StringBuilder sb = new();
49+
foreach (StackFrame frame in _validationError.StackFrames)
50+
{
51+
sb.Append(frame.ToString());
52+
sb.Append(Environment.NewLine);
53+
}
54+
55+
_stackTrace = sb.ToString();
56+
#endif
57+
}
58+
59+
return _stackTrace;
60+
}
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)