Skip to content

Commit

Permalink
Remove use of exception SecurityTokenUnableToValidateException
Browse files Browse the repository at this point in the history
  • Loading branch information
Brent Schmaltz authored and brentschmaltz committed Mar 24, 2023
1 parent 2cdfc47 commit 5d49e7c
Show file tree
Hide file tree
Showing 19 changed files with 296 additions and 625 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1542,16 +1542,13 @@ private static JsonWebToken ValidateSignature(JsonWebToken jwtToken, TokenValida

if (!validationParameters.ValidateSignatureLast)
{
InternalValidators.ValidateLifetimeAndIssuerAfterSignatureNotValidatedJwt(
InternalValidators.ValidateAfterSignatureFailed(
jwtToken,
notBefore,
expires,
jwtToken.Kid,
jwtToken.Audiences,
validationParameters,
configuration,
exceptionStrings,
numKeysInTokenValidationParameters,
numKeysInConfiguration);
configuration);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1084,14 +1084,8 @@ private SamlSecurityToken ValidateSignature(SamlSecurityToken samlToken, string
if (keyMatched)
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSignatureException(LogHelper.FormatInvariant(TokenLogMessages.IDX10514, keysAttempted, samlToken.Assertion.Signature.KeyInfo, exceptionStrings, samlToken)));

if (samlToken.Assertion.Conditions != null)
InternalValidators.ValidateLifetimeAndIssuerAfterSignatureNotValidatedSaml(
samlToken,
samlToken.Assertion.Conditions.NotBefore,
samlToken.Assertion.Conditions.NotOnOrAfter,
samlToken.Assertion.Signature.KeyInfo.ToString(),
validationParameters,
exceptionStrings);
ValidateIssuer(samlToken.Issuer, samlToken, validationParameters);
ValidateConditions(samlToken, validationParameters);
}

if (keysAttempted.Length > 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -466,14 +466,8 @@ private Saml2SecurityToken ValidateSignature(Saml2SecurityToken samlToken, strin
if (keyMatched)
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSignatureException(LogHelper.FormatInvariant(TokenLogMessages.IDX10514, keysAttempted, samlToken.Assertion.Signature.KeyInfo, exceptionStrings, samlToken)));

if (samlToken.Assertion.Conditions != null)
InternalValidators.ValidateLifetimeAndIssuerAfterSignatureNotValidatedSaml(
samlToken,
samlToken.Assertion.Conditions.NotBefore,
samlToken.Assertion.Conditions.NotOnOrAfter,
samlToken.Assertion.Signature.KeyInfo.ToString(),
validationParameters,
exceptionStrings);
ValidateIssuer(samlToken.Issuer, samlToken, validationParameters);
ValidateConditions(samlToken, validationParameters);
}

if (keysAttempted.Length > 0)
Expand Down
127 changes: 8 additions & 119 deletions src/Microsoft.IdentityModel.Tokens/InternalValidators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
// Licensed under the MIT License.

using System;
using System.Text;
using Microsoft.IdentityModel.Logging;
using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages;
using System.Collections.Generic;

namespace Microsoft.IdentityModel.Tokens
{
Expand All @@ -14,128 +12,19 @@ namespace Microsoft.IdentityModel.Tokens
internal static class InternalValidators
{
/// <summary>
/// Called after signature validation has failed. Will always throw an exception.
/// Called after signature validation has failed to avoid a metadata refresh
/// </summary>
/// <exception cref="SecurityTokenSignatureKeyNotFoundException">
/// If the lifetime and issuer are valid
/// </exception>
/// <exception cref="SecurityTokenUnableToValidateException">
/// If the lifetime or issuer are invalid
/// </exception>
internal static void ValidateLifetimeAndIssuerAfterSignatureNotValidatedJwt(
internal static void ValidateAfterSignatureFailed(
SecurityToken securityToken,
DateTime? notBefore,
DateTime? expires,
string kid,
IEnumerable<string> audiences,
TokenValidationParameters validationParameters,
BaseConfiguration configuration,
StringBuilder exceptionStrings,
int numKeysInConfiguration,
int numKeysInTokenValidationParameters)
BaseConfiguration configuration)
{
bool validIssuer = false;
bool validLifetime = false;

try
{
Validators.ValidateLifetime(notBefore, expires, securityToken, validationParameters);
validLifetime = true;
}
catch (Exception)
{
// validLifetime will remain false
}

try
{
Validators.ValidateIssuer(securityToken.Issuer, securityToken, validationParameters, configuration);
validIssuer = true;
}
catch (Exception)
{
// validIssuer will remain false
}

if (validLifetime && validIssuer)
throw LogHelper.LogExceptionMessage(new SecurityTokenSignatureKeyNotFoundException(LogHelper.FormatInvariant(TokenLogMessages.IDX10501,
LogHelper.MarkAsNonPII(kid),
LogHelper.MarkAsNonPII(numKeysInTokenValidationParameters),
LogHelper.MarkAsNonPII(numKeysInConfiguration),
exceptionStrings,
securityToken)));
else
{
var validationFailure = ValidationFailure.None;

if (!validLifetime)
validationFailure |= ValidationFailure.InvalidLifetime;

if (!validIssuer)
validationFailure |= ValidationFailure.InvalidIssuer;

throw LogHelper.LogExceptionMessage(new SecurityTokenUnableToValidateException(
validationFailure,
LogHelper.FormatInvariant(TokenLogMessages.IDX10516,
LogHelper.MarkAsNonPII(kid),
LogHelper.MarkAsNonPII(numKeysInTokenValidationParameters),
LogHelper.MarkAsNonPII(numKeysInConfiguration),
exceptionStrings,
securityToken,
LogHelper.MarkAsNonPII(validLifetime),
LogHelper.MarkAsNonPII(validIssuer))));
}
}

/// <summary>
/// Called after signature validation has failed. Will always throw an exception.
/// </summary>
/// <exception cref="SecurityTokenSignatureKeyNotFoundException">
/// If the lifetime and issuer are valid
/// </exception>
/// <exception cref="SecurityTokenUnableToValidateException">
/// If the lifetime or issuer are invalid
/// </exception>
internal static void ValidateLifetimeAndIssuerAfterSignatureNotValidatedSaml(SecurityToken securityToken, DateTime? notBefore, DateTime? expires, string keyInfo, TokenValidationParameters validationParameters, StringBuilder exceptionStrings)
{
bool validIssuer = false;
bool validLifetime = false;

try
{
Validators.ValidateLifetime(notBefore, expires, securityToken, validationParameters);
validLifetime = true;
}
catch (Exception)
{
// validLifetime will remain false
}

try
{
Validators.ValidateIssuer(securityToken.Issuer, securityToken, validationParameters);
validIssuer = true;
}
catch (Exception)
{
// validIssuer will remain false
}

if (validLifetime && validIssuer)
throw LogHelper.LogExceptionMessage(new SecurityTokenSignatureKeyNotFoundException(LogHelper.FormatInvariant(TokenLogMessages.IDX10513, keyInfo, exceptionStrings, securityToken)));
else
{
var validationFailure = ValidationFailure.None;

if (!validLifetime)
validationFailure |= ValidationFailure.InvalidLifetime;

if (!validIssuer)
validationFailure |= ValidationFailure.InvalidIssuer;

throw LogHelper.LogExceptionMessage(new SecurityTokenUnableToValidateException(
validationFailure,
LogHelper.FormatInvariant(TokenLogMessages.IDX10515, keyInfo, exceptionStrings, securityToken, LogHelper.MarkAsNonPII(validLifetime), LogHelper.MarkAsNonPII(validIssuer))));
}
Validators.ValidateLifetime(notBefore, expires, securityToken, validationParameters);
Validators.ValidateIssuer(securityToken.Issuer, securityToken, validationParameters, configuration);
Validators.ValidateAudience(audiences, securityToken, validationParameters);
}
}
}
8 changes: 4 additions & 4 deletions src/Microsoft.IdentityModel.Tokens/LogMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,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 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 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}'.";
Expand All @@ -93,10 +93,10 @@ internal static class LogMessages
public const string IDX10510 = "IDX10510: Token validation failed. The user defined 'Delegate' set on TokenValidationParameters.TokenReader returned null when reading token: '{0}'.";
public const string IDX10511 = "IDX10511: Signature validation failed. Keys tried: '{0}'. \nNumber of keys in TokenValidationParameters: '{1}'. \nNumber of keys in Configuration: '{2}'. \nMatched key was in '{3}'. \nkid: '{4}'. \nExceptions caught:\n '{5}'.\ntoken: '{6}'. See https://aka.ms/IDX10511 for details.";
public const string IDX10512 = "IDX10512: Signature validation failed. Token does not have KeyInfo. Keys tried: '{0}'.\nExceptions caught:\n '{1}'.\ntoken: '{2}'.";
public const string IDX10513 = "IDX10513: Signature validation failed. Unable to match key: \nKeyInfo: '{0}'.\nExceptions caught:\n '{1}'. \ntoken: '{2}'.";
//public const string IDX10513 = "IDX10513: Signature validation failed. Unable to match key: \nKeyInfo: '{0}'.\nExceptions caught:\n '{1}'. \ntoken: '{2}'.";
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 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}'";

// encryption / decryption
// public const string IDX10600 = "IDX10600:";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1398,16 +1398,13 @@ private JwtSecurityToken ValidateSignature(string token, JwtSecurityToken jwtTok

if (!validationParameters.ValidateSignatureLast)
{
InternalValidators.ValidateLifetimeAndIssuerAfterSignatureNotValidatedJwt(
InternalValidators.ValidateAfterSignatureFailed(
jwtToken,
notBefore,
expires,
jwtToken.Header.Kid,
jwtToken.Audiences,
validationParameters,
configuration,
exceptionStrings,
numKeysInConfiguration,
numKeysInTokenValidationParameters);
configuration);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2194,7 +2194,7 @@ public static TheoryData<CreateTokenTheoryData> RoundTripJWEDirectTestCases
Payload = Default.PayloadString,
SigningCredentials = Default.SymmetricSigningCredentials,
EncryptingCredentials = Default.SymmetricEncryptingCredentials,
ExpectedException = ExpectedException.SecurityTokenUnableToValidateException("IDX10516:")
ExpectedException = ExpectedException.SecurityTokenInvalidIssuerException("IDX10204:")
},
new CreateTokenTheoryData()
{
Expand Down Expand Up @@ -2682,7 +2682,7 @@ public static TheoryData<JwtTheoryData> ValidateJwsTestCases
new JwtTheoryData("SymmetricJws_RequireSignedTokens_KeyNotFound")
{
Token = Default.SymmetricJws,
ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException("IDX10501"),
ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException("IDX10500"),
ValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
Expand All @@ -2707,7 +2707,7 @@ public static TheoryData<JwtTheoryData> ValidateJwsTestCases
},
new JwtTheoryData("SymmetricJws_RequireSignedTokensNullSigningKey")
{
ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException("IDX10501:"),
ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException("IDX10500:"),
Token = Default.SymmetricJws,
ValidationParameters = new TokenValidationParameters
{
Expand Down Expand Up @@ -3308,7 +3308,7 @@ public static TheoryData<CreateTokenTheoryData> SecurityKeyNotFoundExceptionTest
IssuerSigningKey = Default.SymmetricSigningKey,
ValidIssuer = Default.Issuer
},
ExpectedException = ExpectedException.SecurityTokenUnableToValidateException("IDX10516:")
ExpectedException = ExpectedException.SecurityTokenExpiredException("IDX10223:")
},
new CreateTokenTheoryData
{
Expand All @@ -3322,7 +3322,7 @@ public static TheoryData<CreateTokenTheoryData> SecurityKeyNotFoundExceptionTest
{
IssuerSigningKey = Default.SymmetricSigningKey,
},
ExpectedException = ExpectedException.SecurityTokenUnableToValidateException("IDX10516:")
ExpectedException = ExpectedException.SecurityTokenInvalidIssuerException("IDX10204:")
},
new CreateTokenTheoryData
{
Expand All @@ -3339,7 +3339,7 @@ public static TheoryData<CreateTokenTheoryData> SecurityKeyNotFoundExceptionTest
{
IssuerSigningKey = Default.SymmetricSigningKey,
},
ExpectedException = ExpectedException.SecurityTokenUnableToValidateException("IDX10516:")
ExpectedException = ExpectedException.SecurityTokenExpiredException("IDX10223:")
},
new CreateTokenTheoryData
{
Expand All @@ -3353,8 +3353,9 @@ public static TheoryData<CreateTokenTheoryData> SecurityKeyNotFoundExceptionTest
{
IssuerSigningKey = Default.SymmetricSigningKey,
ValidIssuer = Default.Issuer,
ValidateAudience = false
},
ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException("IDX10501:")
ExpectedException = ExpectedException.SecurityTokenSignatureKeyNotFoundException("IDX10503:")
},
};
}
Expand Down
3 changes: 3 additions & 0 deletions test/Microsoft.IdentityModel.TestUtils/TokenTheoryData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ public class TokenTheoryData : TheoryDataBase
{
public TokenTheoryData()
{
}

public TokenTheoryData(string testId) : base(testId)
{
}

public TokenTheoryData(TokenTheoryData other)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Collections.Generic;
using Microsoft.IdentityModel.TestUtils;
using Microsoft.IdentityModel.Tokens.Saml2;

#pragma warning disable CS3016 // Arrays as attribute arguments is not CLS-compliant

namespace Microsoft.IdentityModel.Tokens.Saml.Tests
{
public class CreateTokenTheoryData : TheoryDataBase
{
public Dictionary<string, object> AdditionalHeaderClaims { get; set; }

public string Payload { get; set; }

public string CompressionAlgorithm { get; set; }

public CompressionProviderFactory CompressionProviderFactory { get; set; }

public EncryptingCredentials EncryptingCredentials { get; set; }

public bool IsValid { get; set; } = true;

public SigningCredentials SigningCredentials { get; set; }

public SecurityTokenDescriptor TokenDescriptor { get; set; }

public SamlSecurityTokenHandler SamlSecurityTokenHandler { get; set; }

public Saml2SecurityTokenHandler Saml2SecurityTokenHandler { get; set; }

public string SamlToken { get; set; }

public TokenValidationParameters ValidationParameters { get; set; }
}
}

#pragma warning restore CS3016 // Arrays as attribute arguments is not CLS-compliant
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
using System;
using System.Runtime.InteropServices;

[assembly: CLSCompliant(true)]
[assembly: CLSCompliant(false)]
[assembly: ComVisible(false)]
Loading

0 comments on commit 5d49e7c

Please sign in to comment.