Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Microsoft.IdentityModel.Logging;
using Microsoft.IdentityModel.Tokens;
Expand Down Expand Up @@ -139,10 +140,14 @@ private static ValidationResult<SecurityKey, ValidationError> ValidateSignatureU
StringBuilder? exceptionStrings = null;
StringBuilder? keysAttempted = null;

// We want to capture all stack frames that were involved with faults.
// We capture the stack frames and add to the error.
IList<StackFrame>? stackFrames = null;

foreach (SecurityKey key in keys)
{
if (key is null)
continue; // skip null keys
continue;

keysTried = true;

Expand All @@ -154,68 +159,94 @@ private static ValidationResult<SecurityKey, ValidationError> ValidateSignatureU
callContext);

if (result.Succeeded)
{
jwtToken.SigningKey = key;
return result;
}

if (result.Error is ValidationError validationError)
{
stackFrames ??= [];
foreach (StackFrame stackFrame in validationError.StackFrames)
stackFrames.Add(stackFrame);

exceptionStrings ??= new StringBuilder();
keysAttempted ??= new StringBuilder();
exceptionStrings.AppendLine(validationError.MessageDetail.Message);
keysAttempted.AppendLine(key.ToString());
}
}

// This method tries a number of different keys, for each failure we add a stack frame to the stackFrames collection.
// We want to add the current stack frame to the end of the list, to keep the order of the stack frames.
// If for some reason stackFrames is null or empty, we add the current stack frame as the first and only entry.
StackFrame currentStackFrame = ValidationError.GetCurrentStackFrame();
StackFrame firstStackFrame = (stackFrames == null || stackFrames.Count == 0) ? currentStackFrame : stackFrames[0];
SignatureValidationError signatureValidationError;

if (keysTried)
{
if (kidExists)
{
return new SignatureValidationError(
signatureValidationError = new SignatureValidationError(
new MessageDetail(
TokenLogMessages.IDX10522,
LogHelper.MarkAsNonPII(jwtToken.Kid),
LogHelper.MarkAsNonPII(validationParameters.SigningKeys.Count),
LogHelper.MarkAsNonPII(configuration?.SigningKeys?.Count ?? 0),
LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)),
SignatureValidationFailure.SigningKeyNotFound,
ValidationError.GetCurrentStackFrame());
firstStackFrame);
}
else
{
return new SignatureValidationError(
signatureValidationError = new SignatureValidationError(
new MessageDetail(
TokenLogMessages.IDX10523,
LogHelper.MarkAsNonPII(validationParameters.SigningKeys.Count),
LogHelper.MarkAsNonPII(configuration?.SigningKeys?.Count ?? 0),
LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)),
SignatureValidationFailure.SigningKeyNotFound,
ValidationError.GetCurrentStackFrame());
firstStackFrame);
}
}

if (kidExists)
else if (kidExists)
{
// No keys were attempted, return the error.
// This is the case where the user specified a kid, but no keys were found.
// This is not an error, but a warning that no keys were found for the specified kid.
return new SignatureValidationError(
// There is a kid, but no keys were found.
signatureValidationError = new SignatureValidationError(
new MessageDetail(
TokenLogMessages.IDX10524,
LogHelper.MarkAsNonPII(jwtToken.Kid),
LogHelper.MarkAsNonPII(validationParameters.SigningKeys.Count),
LogHelper.MarkAsNonPII(configuration?.SigningKeys?.Count ?? 0),
LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)),
SignatureValidationFailure.SigningKeyNotFound,
ValidationError.GetCurrentStackFrame());
firstStackFrame);
}
else
{
signatureValidationError = new SignatureValidationError(
new MessageDetail(
TokenLogMessages.IDX10525,
LogHelper.MarkAsNonPII(validationParameters.SigningKeys.Count),
LogHelper.MarkAsNonPII(configuration?.SigningKeys?.Count ?? 0),
LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)),
SignatureValidationFailure.SigningKeyNotFound,
firstStackFrame);
}

return new SignatureValidationError(
new MessageDetail(
TokenLogMessages.IDX10525,
LogHelper.MarkAsNonPII(validationParameters.SigningKeys.Count),
LogHelper.MarkAsNonPII(configuration?.SigningKeys?.Count ?? 0),
LogHelper.MarkAsSecurityArtifact(jwtToken.EncodedToken, JwtTokenUtilities.SafeLogJwtToken)),
SignatureValidationFailure.SigningKeyNotFound,
ValidationError.GetCurrentStackFrame());
if (stackFrames != null)
{
for (int i = 1; i < stackFrames.Count; i++)
{
if (stackFrames[i] != null)
signatureValidationError.StackFrames.Add(stackFrames[i]);
}

signatureValidationError.StackFrames.Add(currentStackFrame);
}

return signatureValidationError;
}

private static ValidationResult<SecurityKey, ValidationError> ValidateSignatureWithKey(
Expand All @@ -234,7 +265,7 @@ private static ValidationResult<SecurityKey, ValidationError> ValidateSignatureW
TokenLogMessages.IDX10652,
LogHelper.MarkAsNonPII(jsonWebToken.Alg),
key),
AlgorithmValidationFailure.AlgorithmIsNotSupported,
AlgorithmValidationFailure.NotSupported,
ValidationError.GetCurrentStackFrame());
}

Expand Down
Loading
Loading