Skip to content

Commit

Permalink
Optmise IDX10503 (#2436)
Browse files Browse the repository at this point in the history
* Optmise IDX10503

* add a new SecurityTokenSignatureKeyNotFoundExceptionwhen kid is empty

* update message id

* fix test
  • Loading branch information
ciaozhang authored Jan 10, 2024
1 parent c1be3d6 commit 54face8
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 25 deletions.
29 changes: 22 additions & 7 deletions src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -962,7 +962,7 @@ private static JsonWebToken ValidateSignature(JsonWebToken jwtToken, TokenValida
var isKidInTVP = keysInTokenValidationParameters.Any(x => x.KeyId.Equals(localJwtToken.Kid));
var keyLocation = isKidInTVP ? "TokenValidationParameters" : "Configuration";
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSignatureException(LogHelper.FormatInvariant(TokenLogMessages.IDX10511,
(object)keysAttempted ?? "",
LogHelper.MarkAsNonPII((object)keysAttempted ?? ""),
LogHelper.MarkAsNonPII(numKeysInTokenValidationParameters),
LogHelper.MarkAsNonPII(numKeysInConfiguration),
LogHelper.MarkAsNonPII(keyLocation),
Expand All @@ -984,12 +984,27 @@ private static JsonWebToken ValidateSignature(JsonWebToken jwtToken, TokenValida
}

if (keysAttempted is not null)
throw LogHelper.LogExceptionMessage(new SecurityTokenSignatureKeyNotFoundException(LogHelper.FormatInvariant(TokenLogMessages.IDX10503,
keysAttempted,
LogHelper.MarkAsNonPII(numKeysInTokenValidationParameters),
LogHelper.MarkAsNonPII(numKeysInConfiguration),
(object)exceptionStrings ?? "",
jwtToken)));
{
if (kidExists)
{
throw LogHelper.LogExceptionMessage(new SecurityTokenSignatureKeyNotFoundException(LogHelper.FormatInvariant(TokenLogMessages.IDX10503,
LogHelper.MarkAsNonPII(jwtToken.Kid),
LogHelper.MarkAsNonPII((object)keysAttempted ?? ""),
LogHelper.MarkAsNonPII(numKeysInTokenValidationParameters),
LogHelper.MarkAsNonPII(numKeysInConfiguration),
(object)exceptionStrings ?? "",
jwtToken)));
}
else
{
throw LogHelper.LogExceptionMessage(new SecurityTokenSignatureKeyNotFoundException(LogHelper.FormatInvariant(TokenLogMessages.IDX10517,
LogHelper.MarkAsNonPII((object)keysAttempted ?? ""),
LogHelper.MarkAsNonPII(numKeysInTokenValidationParameters),
LogHelper.MarkAsNonPII(numKeysInConfiguration),
(object)exceptionStrings ?? "",
jwtToken)));
}
}

throw LogHelper.LogExceptionMessage(new SecurityTokenSignatureKeyNotFoundException(TokenLogMessages.IDX10500));
}
Expand Down
3 changes: 2 additions & 1 deletion src/Microsoft.IdentityModel.Tokens/LogMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ internal static class LogMessages
// 10500 - SignatureValidation
public const string IDX10500 = "IDX10500: Signature validation failed. No security keys were provided to validate the signature.";
//public const string IDX10501 = "IDX10501: 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}'.";
public const string IDX10503 = "IDX10503: Signature validation failed. Token does not have a kid. 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 IDX10503 = "IDX10503: Signature validation failed. The token's kid is: '{0}', but did not match any keys in TokenValidationParameters or Configuration. Keys tried: '{1}'. Number of keys in TokenValidationParameters: '{2}'. \nNumber of keys in Configuration: '{3}'. \nExceptions caught:\n '{4}'.\ntoken: '{5}'. See https://aka.ms/IDX10503 for details.";
public const string IDX10504 = "IDX10504: Unable to validate signature, token does not have a signature: '{0}'.";
public const string IDX10505 = "IDX10505: Signature validation failed. The user defined 'Delegate' specified on TokenValidationParameters returned null when validating token: '{0}'.";
public const string IDX10506 = "IDX10506: Signature validation failed. The user defined 'Delegate' specified on TokenValidationParameters did not return a '{0}', but returned a '{1}' when validating token: '{2}'.";
Expand All @@ -97,6 +97,7 @@ internal static class LogMessages
public const string IDX10514 = "IDX10514: Signature validation failed. Keys tried: '{0}'. \nKeyInfo: '{1}'. \nExceptions caught:\n '{2}'.\ntoken: '{3}'.";
//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.";

// encryption / decryption
// public const string IDX10600 = "IDX10600:";
Expand Down
44 changes: 30 additions & 14 deletions src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1358,8 +1358,8 @@ private JwtSecurityToken ValidateSignature(string token, JwtSecurityToken jwtTok
}

// keep track of exceptions thrown, keys that were tried
var exceptionStrings = new StringBuilder();
var keysAttempted = new StringBuilder();
StringBuilder exceptionStrings = null;
StringBuilder keysAttempted = null;
bool kidExists = !string.IsNullOrEmpty(jwtToken.Header.Kid);
byte[] signatureBytes;

Expand Down Expand Up @@ -1389,12 +1389,12 @@ private JwtSecurityToken ValidateSignature(string token, JwtSecurityToken jwtTok
}
catch (Exception ex)
{
exceptionStrings.AppendLine(ex.ToString());
(exceptionStrings ??= new StringBuilder()).AppendLine(ex.ToString());
}

if (key != null)
{
keysAttempted.Append(key.ToString()).Append(" , KeyId: ").AppendLine(key.KeyId);
(keysAttempted ??= new StringBuilder()).Append(key.ToString()).Append(" , KeyId: ").AppendLine(key.KeyId);
if (kidExists && !kidMatched && key.KeyId != null)
kidMatched = jwtToken.Header.Kid.Equals(key.KeyId, key is X509SecurityKey ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
}
Expand All @@ -1412,15 +1412,16 @@ private JwtSecurityToken ValidateSignature(string token, JwtSecurityToken jwtTok
{
if (kidMatched)
{
var isKidInTVP = keysInTokenValidationParameters.Any(x => x.KeyId.Equals(jwtToken.Header.Kid));
JwtSecurityToken localJwtToken = jwtToken; // avoid closure on non-exceptional path
var isKidInTVP = keysInTokenValidationParameters.Any(x => x.KeyId.Equals(localJwtToken.Header.Kid));
var keyLocation = isKidInTVP ? "TokenValidationParameters" : "Configuration";
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSignatureException(LogHelper.FormatInvariant(TokenLogMessages.IDX10511,
keysAttempted,
LogHelper.MarkAsNonPII((object)keysAttempted ?? ""),
LogHelper.MarkAsNonPII(numKeysInTokenValidationParameters),
LogHelper.MarkAsNonPII(numKeysInConfiguration),
LogHelper.MarkAsNonPII(keyLocation),
LogHelper.MarkAsNonPII(jwtToken.Header.Kid),
exceptionStrings,
(object)exceptionStrings ?? "",
jwtToken)));
}

Expand All @@ -1439,13 +1440,28 @@ private JwtSecurityToken ValidateSignature(string token, JwtSecurityToken jwtTok
}
}

if (keysAttempted.Length > 0)
throw LogHelper.LogExceptionMessage(new SecurityTokenSignatureKeyNotFoundException(LogHelper.FormatInvariant(TokenLogMessages.IDX10503,
keysAttempted,
LogHelper.MarkAsNonPII(numKeysInTokenValidationParameters),
LogHelper.MarkAsNonPII(numKeysInConfiguration),
exceptionStrings,
jwtToken)));
if (keysAttempted is not null)
{
if (kidExists)
{
throw LogHelper.LogExceptionMessage(new SecurityTokenSignatureKeyNotFoundException(LogHelper.FormatInvariant(TokenLogMessages.IDX10503,
LogHelper.MarkAsNonPII(jwtToken.Header.Kid),
LogHelper.MarkAsNonPII((object)keysAttempted ?? ""),
LogHelper.MarkAsNonPII(numKeysInTokenValidationParameters),
LogHelper.MarkAsNonPII(numKeysInConfiguration),
(object)exceptionStrings ?? "",
jwtToken)));
}
else
{
throw LogHelper.LogExceptionMessage(new SecurityTokenSignatureKeyNotFoundException(LogHelper.FormatInvariant(TokenLogMessages.IDX10517,
LogHelper.MarkAsNonPII((object)keysAttempted ?? ""),
LogHelper.MarkAsNonPII(numKeysInTokenValidationParameters),
LogHelper.MarkAsNonPII(numKeysInConfiguration),
(object)exceptionStrings ?? "",
jwtToken)));
}
}

throw LogHelper.LogExceptionMessage(new SecurityTokenSignatureKeyNotFoundException(TokenLogMessages.IDX10500));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ public void MatchX5t()
validateKey = KeyingMaterial.X509SecurityKeySelfSigned2048_SHA384_Public;
validationParameters.IssuerSigningKey = validateKey;

ExpectedException expectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException("IDX10503:");
ExpectedException expectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException("IDX10517:");
try
{
cp = handler.ValidateToken(jwt, validationParameters, out validatedSecurityToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1962,7 +1962,7 @@ public static TheoryData<JwtTheoryData> ValidateSignatureTheoryData
{
new JwtTheoryData
{
ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException(substringExpected: "IDX10503:"),
ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException(substringExpected: "IDX10517:"),
TestId = "Security Key Identifier not found",
Token = JwtTestUtilities.GetJwtParts(EncodedJwts.Asymmetric_2048, "ALLParts"),
ValidationParameters = ValidateSignatureValidationParameters(KeyingMaterial.X509SecurityKey_LocalSts, null)
Expand Down Expand Up @@ -2083,7 +2083,7 @@ public static TheoryData<JwtTheoryData> ValidateSignatureTheoryData
},
new JwtTheoryData
{
ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException(substringExpected: "IDX10503:"),
ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException(substringExpected: "IDX10517:"),
TestId = "BinaryKey 56Bits",
Token = JwtTestUtilities.GetJwtParts(EncodedJwts.Symmetric_256, "ALLParts"),
ValidationParameters = ValidateSignatureValidationParameters(KeyingMaterial.DefaultSymmetricSecurityKey_56, null),
Expand Down

0 comments on commit 54face8

Please sign in to comment.