Skip to content

Commit

Permalink
Handle potential exception thrown by the lifetime validation delegate…
Browse files Browse the repository at this point in the history
… in JWT, SAML, and SAML2
  • Loading branch information
iNinja committed Nov 17, 2024
1 parent 2609624 commit 8b6f130
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -255,13 +255,28 @@ private async ValueTask<ValidationResult<ValidatedToken>> ValidateJWSAsync(
DateTime? expires = jsonWebToken.HasPayloadClaim(JwtRegisteredClaimNames.Exp) ? jsonWebToken.ValidTo : null;
DateTime? notBefore = jsonWebToken.HasPayloadClaim(JwtRegisteredClaimNames.Nbf) ? jsonWebToken.ValidFrom : null;

ValidationResult<ValidatedLifetime> lifetimeValidationResult = validationParameters.LifetimeValidator(
notBefore, expires, jsonWebToken, validationParameters, callContext);
ValidationResult<ValidatedLifetime> lifetimeValidationResult;

if (!lifetimeValidationResult.IsValid)
try
{
StackFrame lifetimeValidationFailureStackFrame = StackFrames.LifetimeValidationFailed ??= new StackFrame(true);
return lifetimeValidationResult.UnwrapError().AddStackFrame(lifetimeValidationFailureStackFrame);
lifetimeValidationResult = validationParameters.LifetimeValidator(
notBefore, expires, jsonWebToken, validationParameters, callContext);

if (!lifetimeValidationResult.IsValid)
return lifetimeValidationResult.UnwrapError().AddCurrentStackFrame();
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
return new LifetimeValidationError(
new MessageDetail(TokenLogMessages.IDX10271),
typeof(SecurityTokenInvalidLifetimeException),
ValidationError.GetCurrentStackFrame(),
notBefore,
expires,
ValidationFailureType.LifetimeValidatorThrew,
ex);
}

if (jsonWebToken.Audiences is not IList<string> tokenAudiences)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,17 +126,32 @@ internal virtual ValidationResult<ValidatedConditions> ValidateConditions(
StackFrames.AssertionConditionsNull);
}

var lifetimeValidationResult = validationParameters.LifetimeValidator(
samlToken.Assertion.Conditions.NotBefore,
samlToken.Assertion.Conditions.NotOnOrAfter,
samlToken,
validationParameters,
callContext);
ValidationResult<ValidatedLifetime> lifetimeValidationResult;

if (!lifetimeValidationResult.IsValid)
try
{
lifetimeValidationResult = validationParameters.LifetimeValidator(
samlToken.Assertion.Conditions.NotBefore,
samlToken.Assertion.Conditions.NotOnOrAfter,
samlToken,
validationParameters,
callContext);

if (!lifetimeValidationResult.IsValid)
return lifetimeValidationResult.UnwrapError().AddCurrentStackFrame();
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
StackFrames.LifetimeValidationFailed ??= new StackFrame(true);
return lifetimeValidationResult.UnwrapError().AddStackFrame(StackFrames.LifetimeValidationFailed);
return new LifetimeValidationError(
new MessageDetail(Tokens.LogMessages.IDX10271),
typeof(SecurityTokenInvalidLifetimeException),
ValidationError.GetCurrentStackFrame(),
samlToken.Assertion.Conditions.NotBefore,
samlToken.Assertion.Conditions.NotOnOrAfter,
ValidationFailureType.LifetimeValidatorThrew,
ex);
}

string? validatedAudience = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,17 +129,32 @@ internal virtual ValidationResult<ValidatedConditions> ValidateConditions(
StackFrames.AssertionConditionsNull);
}

var lifetimeValidationResult = validationParameters.LifetimeValidator(
samlToken.Assertion.Conditions.NotBefore,
samlToken.Assertion.Conditions.NotOnOrAfter,
samlToken,
validationParameters,
callContext);
ValidationResult<ValidatedLifetime> lifetimeValidationResult;

if (!lifetimeValidationResult.IsValid)
try
{
StackFrames.LifetimeValidationFailed ??= new StackFrame(true);
return lifetimeValidationResult.UnwrapError().AddStackFrame(StackFrames.LifetimeValidationFailed);
lifetimeValidationResult = validationParameters.LifetimeValidator(
samlToken.Assertion.Conditions.NotBefore,
samlToken.Assertion.Conditions.NotOnOrAfter,
samlToken,
validationParameters,
callContext);

if (!lifetimeValidationResult.IsValid)
return lifetimeValidationResult.UnwrapError().AddCurrentStackFrame();
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
return new LifetimeValidationError(
new MessageDetail(Tokens.LogMessages.IDX10271),
typeof(SecurityTokenInvalidLifetimeException),
ValidationError.GetCurrentStackFrame(),
samlToken.Assertion.Conditions.NotBefore,
samlToken.Assertion.Conditions.NotOnOrAfter,
ValidationFailureType.LifetimeValidatorThrew,
ex);
}

if (samlToken.Assertion.Conditions.OneTimeUse)
Expand Down
2 changes: 2 additions & 0 deletions src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const Microsoft.IdentityModel.Tokens.LogMessages.IDX10002 = "IDX10002: Unknown exception type returned. Type: '{0}'. Message: '{1}'." -> string
const Microsoft.IdentityModel.Tokens.LogMessages.IDX10268 = "IDX10268: Unable to validate audience, validationParameters.ValidAudiences.Count == 0." -> string
const Microsoft.IdentityModel.Tokens.LogMessages.IDX10269 = "IDX10269: IssuerValidationDelegate threw an exception, see inner exception." -> string
const Microsoft.IdentityModel.Tokens.LogMessages.IDX10271 = "IDX10271: LifetimeValidationDelegate threw an exception, see inner exception." -> string
Microsoft.IdentityModel.Tokens.AlgorithmValidationError
Microsoft.IdentityModel.Tokens.AlgorithmValidationError.AlgorithmValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, string invalidAlgorithm, Microsoft.IdentityModel.Tokens.ValidationFailureType validationFailureType = null, System.Exception innerException = null) -> void
Microsoft.IdentityModel.Tokens.AlgorithmValidationError.InvalidAlgorithm.get -> string
Expand Down Expand Up @@ -42,6 +43,7 @@ static Microsoft.IdentityModel.Tokens.AudienceValidationError.ValidationParamete
static Microsoft.IdentityModel.Tokens.Utility.SerializeAsSingleCommaDelimitedString(System.Collections.Generic.IList<string> strings) -> string
static Microsoft.IdentityModel.Tokens.ValidationError.GetCurrentStackFrame(string filePath = "", int lineNumber = 0, int skipFrames = 1) -> System.Diagnostics.StackFrame
static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.IssuerValidatorThrew -> Microsoft.IdentityModel.Tokens.ValidationFailureType
static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.LifetimeValidatorThrew -> Microsoft.IdentityModel.Tokens.ValidationFailureType
static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.NoTokenAudiencesProvided -> Microsoft.IdentityModel.Tokens.ValidationFailureType
static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.NoValidationParameterAudiencesProvided -> Microsoft.IdentityModel.Tokens.ValidationFailureType
static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.SignatureAlgorithmValidationFailed -> Microsoft.IdentityModel.Tokens.ValidationFailureType
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.IdentityModel.Tokens/LogMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ internal static class LogMessages
public const string IDX10267 = "IDX10267: '{0}' has been called by a derived class '{1}' which has not implemented this method. For this call graph to succeed, '{1}' will need to implement '{0}'.";
public const string IDX10268 = "IDX10268: Unable to validate audience, validationParameters.ValidAudiences.Count == 0.";
public const string IDX10269 = "IDX10269: IssuerValidationDelegate threw an exception, see inner exception.";

public const string IDX10271 = "IDX10271: LifetimeValidationDelegate threw an exception, see inner exception.";

// 10500 - SignatureValidation
public const string IDX10500 = "IDX10500: Signature validation failed. No security keys were provided to validate the signature.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,10 @@ private class XmlValidationFailure : ValidationFailureType { internal XmlValidat
/// </summary>
public static readonly ValidationFailureType IssuerValidatorThrew = new IssuerValidatorFailure("IssuerValidatorThrew");
private class IssuerValidatorFailure : ValidationFailureType { internal IssuerValidatorFailure(string name) : base(name) { } }

/// <summary>
/// Defines a type that represents that the audience validation delegate threw and exception.
/// </summary>
public static readonly ValidationFailureType LifetimeValidatorThrew = new LifetimeValidationFailure("LifetimeValidatorThrew");
}
}

0 comments on commit 8b6f130

Please sign in to comment.