Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression tests: Added inner exception detail and invalid signature failure due to invalid algorithm used #2811

Merged
merged 4 commits into from
Sep 6, 2024
Merged
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 @@ -241,7 +241,14 @@ private static Result<SecurityKey> ValidateSignatureWithKey(
callContext);

if (!result.IsSuccess)
return new(result.UnwrapError()); // Because we return an interface type, we need to explicitly create the Result.
return new ExceptionDetail(
new MessageDetail(
TokenLogMessages.IDX10518,
result.UnwrapError().MessageDetail.Message),
ValidationFailureType.SignatureValidationFailed,
typeof(SecurityTokenInvalidSignatureException),
new StackFrame(true),
result.UnwrapError());

SignatureProvider signatureProvider = cryptoProviderFactory.CreateForVerifying(key, jsonWebToken.Alg);
try
Expand Down
1 change: 1 addition & 0 deletions src/Microsoft.IdentityModel.Tokens/LogMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ internal static class LogMessages
//public const string IDX10515 = "IDX10515: Signature validation failed. Unable to match key: \nKeyInfo: '{0}'.\nExceptions caught:\n '{1}'. \ntoken: '{2}'. Valid Lifetime: '{3}'. Valid Issuer: '{4}'";
//public const string IDX10516 = "IDX10516: Signature validation failed. Unable to match key: \nkid: '{0}'. \nNumber of keys in TokenValidationParameters: '{1}'. \nNumber of keys in Configuration: '{2}'. \nExceptions caught:\n '{3}'. \ntoken: '{4}'. Valid Lifetime: '{5}'. Valid Issuer: '{6}'";
public const string IDX10517 = "IDX10517: Signature validation failed. The token's kid is missing. Keys tried: '{0}'. Number of keys in TokenValidationParameters: '{1}'. \nNumber of keys in Configuration: '{2}'. \nExceptions caught:\n '{3}'.\ntoken: '{4}'. See https://aka.ms/IDX10503 for details.";
public const string IDX10518 = "IDX10518: Signature validation failed. Algorithm validation failed with error: '{0}'.";

// encryption / decryption
// public const string IDX10600 = "IDX10600:";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public ExceptionDetail(
ValidationFailureType failureType,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type exceptionType,
StackFrame stackFrame)
: this(MessageDetail, failureType, exceptionType, stackFrame, null)
: this(MessageDetail, failureType, exceptionType, stackFrame, innerException: null)
{
}

Expand Down Expand Up @@ -57,17 +57,37 @@ public ExceptionDetail(
};
}

public ExceptionDetail(
MessageDetail messageDetail,
ValidationFailureType failureType,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type exceptionType,
StackFrame stackFrame,
ExceptionDetail innerExceptionDetail)
{
InnerExceptionDetail = innerExceptionDetail;
MessageDetail = messageDetail;
_exceptionType = exceptionType;
FailureType = failureType;
StackFrames = new List<StackFrame>(4)
keegan-caruso marked this conversation as resolved.
Show resolved Hide resolved
{
stackFrame
};
}

/// <summary>
/// Creates an instance of an <see cref="Exception"/> using <see cref="ExceptionDetail"/>
/// </summary>
/// <returns>An instantance of an Exception.</returns>
public Exception GetException()
{
Exception exception;
if (InnerException == null)
if (InnerException == null && InnerExceptionDetail == null)
exception = Activator.CreateInstance(_exceptionType, MessageDetail.Message) as Exception;
else
exception = Activator.CreateInstance(_exceptionType, MessageDetail.Message, InnerException) as Exception;
exception = Activator.CreateInstance(
_exceptionType,
MessageDetail.Message,
InnerException ?? InnerExceptionDetail.GetException()) as Exception;

if (exception is SecurityTokenException securityTokenException)
securityTokenException.ExceptionDetail = this;
Expand Down Expand Up @@ -103,6 +123,11 @@ protected virtual void AddAdditionalInformation(Exception exception)
/// </summary>
public Exception InnerException { get; }

/// <summary>
/// Gets the details for the inner exception that occurred.
/// </summary>
public ExceptionDetail InnerExceptionDetail { get; }

/// <summary>
/// Gets the message details that are used to generate the exception message.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,32 @@ public static TheoryData<JsonWebTokenHandlerValidationParametersTheoryData> Json
ExpectedIsValid = false,
ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException("IDX10517:"),
},
new JsonWebTokenHandlerValidationParametersTheoryData("Invalid_TokenSignedWithInvalidAlgorithm")
{
// Token is signed with HmacSha256 but only sha256 is considered valid for this test's purposes
TokenValidationParameters = CreateTokenValidationParameters(
Default.Issuer, [Default.Audience], KeyingMaterial.DefaultSymmetricSigningCreds_256_Sha2.Key,
validAlgorithms: [SecurityAlgorithms.Sha256]),
ValidationParameters = CreateValidationParameters(
Default.Issuer, [Default.Audience], KeyingMaterial.DefaultSymmetricSigningCreds_256_Sha2.Key,
validAlgorithms: [SecurityAlgorithms.Sha256]),
SigningCredentials = KeyingMaterial.DefaultSymmetricSigningCreds_256_Sha2,
ExpectedIsValid = false,
ExpectedException = ExpectedException.SecurityTokenInvalidSignatureException("IDX10511:"),
ExpectedExceptionValidationParameters = ExpectedException.SecurityTokenInvalidSignatureException(
"IDX10518:",
innerTypeExpected: typeof(SecurityTokenInvalidAlgorithmException))
},
};

static TokenValidationParameters CreateTokenValidationParameters(
string issuer,
List<string> audiences,
SecurityKey issuerSigningKey,
List<string> validAlgorithms = null,
bool tryAllKeys = false) => new TokenValidationParameters
{
ValidAlgorithms = validAlgorithms,
ValidateAudience = true,
ValidateIssuer = true,
ValidateLifetime = true,
Expand All @@ -209,13 +227,16 @@ static ValidationParameters CreateValidationParameters(
string issuer,
List<string> audiences,
SecurityKey issuerSigningKey,
List<string> validAlgorithms = null,
bool tryAllKeys = false)
{
ValidationParameters validationParameters = new ValidationParameters();
validationParameters.ValidIssuers.Add(issuer);
audiences.ForEach(audience => validationParameters.ValidAudiences.Add(audience));
validationParameters.IssuerSigningKeys.Add(issuerSigningKey);
validationParameters.TryAllIssuerSigningKeys = tryAllKeys;
if (validAlgorithms is not null)
validationParameters.ValidAlgorithms = validAlgorithms;

return validationParameters;
}
Expand Down
Loading