Skip to content

Commit

Permalink
Merge branch 'dev' into iinglese/new-model-validation-for-saml-algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
iNinja authored Nov 8, 2024
2 parents 4e95142 + 8dc81e6 commit 0409662
Show file tree
Hide file tree
Showing 22 changed files with 1,138 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.EncryptToken(byte[] innerTokenUtf8Bytes, Microsoft.IdentityModel.Tokens.EncryptingCredentials encryptingCredentials, string compressionAlgorithm, System.Collections.Generic.IDictionary<string, object> additionalHeaderClaims, string tokenType, bool includeKeyIdInHeader) -> string
static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.WriteJweHeader(Microsoft.IdentityModel.Tokens.EncryptingCredentials encryptingCredentials, string compressionAlgorithm, string tokenType, System.Collections.Generic.IDictionary<string, object> jweHeaderClaims, bool includeKeyIdInHeader) -> byte[]
static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.WriteJwsHeader(ref System.Text.Json.Utf8JsonWriter writer, Microsoft.IdentityModel.Tokens.SigningCredentials signingCredentials, Microsoft.IdentityModel.Tokens.EncryptingCredentials encryptingCredentials, System.Collections.Generic.IDictionary<string, object> jweHeaderClaims, System.Collections.Generic.IDictionary<string, object> jwsHeaderClaims, string tokenType, bool includeKeyIdInHeader) -> void
static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.WriteJwsHeader(ref System.Text.Json.Utf8JsonWriter writer, Microsoft.IdentityModel.Tokens.SigningCredentials signingCredentials, Microsoft.IdentityModel.Tokens.EncryptingCredentials encryptingCredentials, System.Collections.Generic.IDictionary<string, object> jweHeaderClaims, System.Collections.Generic.IDictionary<string, object> jwsHeaderClaims, string tokenType, bool includeKeyIdInHeader) -> void
static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.StackFrames.IssuerValidatorThrew -> System.Diagnostics.StackFrame
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,7 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration,
if (result.IsValid)
return result;

StackFrame tokenValidationStackFrame = StackFrames.TokenValidationFailedNullConfigurationManager ??= new StackFrame(true);
return result.UnwrapError().AddStackFrame(tokenValidationStackFrame);
return result.UnwrapError().AddStackFrame(ValidationError.GetCurrentStackFrame());
}

if (result.IsValid)
Expand Down Expand Up @@ -277,14 +276,29 @@ private async ValueTask<ValidationResult<ValidatedToken>> ValidateJWSAsync(
return audienceValidationResult.UnwrapError().AddStackFrame(audienceValidationFailureStackFrame);
}

ValidationResult<ValidatedIssuer> issuerValidationResult = await validationParameters.IssuerValidatorAsync(
jsonWebToken.Issuer, jsonWebToken, validationParameters, callContext, cancellationToken)
.ConfigureAwait(false);
ValidationResult<ValidatedIssuer> issuerValidationResult;
try
{
issuerValidationResult = await validationParameters.IssuerValidatorAsync(
jsonWebToken.Issuer, jsonWebToken, validationParameters, callContext, cancellationToken)
.ConfigureAwait(false);

if (!issuerValidationResult.IsValid)
if (!issuerValidationResult.IsValid)
{
return issuerValidationResult.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
{
StackFrame issuerValidationFailureStackFrame = StackFrames.IssuerValidationFailed ??= new StackFrame(true);
return issuerValidationResult.UnwrapError().AddStackFrame(issuerValidationFailureStackFrame);
return new IssuerValidationError(
new MessageDetail(TokenLogMessages.IDX10269),
ValidationFailureType.IssuerValidatorThrew,
typeof(SecurityTokenInvalidIssuerException),
ValidationError.GetCurrentStackFrame(),
jsonWebToken.Issuer,
ex);
}

ValidationResult<DateTime?> replayValidationResult = validationParameters.TokenReplayValidator(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ internal static class StackFrames
internal static StackFrame? TokenNull;
internal static StackFrame? TokenValidationParametersNull;
internal static StackFrame? TokenNotJWT;
internal static StackFrame? TokenValidationFailedNullConfigurationManager;
internal static StackFrame? TokenValidationFailed;
// ValidateJWEAsync
internal static StackFrame? DecryptionFailed;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Microsoft.IdentityModel.Tokens.Saml2.Saml2ValidationError.Saml2ValidationError(M
Microsoft.IdentityModel.Tokens.Saml2.Saml2ValidationError.Saml2ValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, Microsoft.IdentityModel.Tokens.ValidationFailureType failureType, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, System.Exception innerException) -> void
override Microsoft.IdentityModel.Tokens.Saml.SamlValidationError.GetException() -> System.Exception
override Microsoft.IdentityModel.Tokens.Saml2.Saml2ValidationError.GetException() -> System.Exception
static Microsoft.IdentityModel.Tokens.Saml.SamlSecurityTokenHandler.StackFrames.IssuerSigningKeyValidationFailed -> System.Diagnostics.StackFrame
static Microsoft.IdentityModel.Tokens.Saml.SamlSecurityTokenHandler.StackFrames.IssuerValidationFailed -> System.Diagnostics.StackFrame
static Microsoft.IdentityModel.Tokens.Saml.SamlSecurityTokenHandler.StackFrames.SignatureValidationFailed -> System.Diagnostics.StackFrame
static Microsoft.IdentityModel.Tokens.Saml.SamlSecurityTokenHandler.ValidateSignature(Microsoft.IdentityModel.Tokens.Saml.SamlSecurityToken samlToken, Microsoft.IdentityModel.Tokens.ValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.CallContext callContext) -> Microsoft.IdentityModel.Tokens.ValidationResult<Microsoft.IdentityModel.Tokens.SecurityKey>
Expand All @@ -38,6 +39,7 @@ static Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.StackFrame
static Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.StackFrames.AssertionConditionsValidationFailed -> System.Diagnostics.StackFrame
static Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.StackFrames.AssertionNull -> System.Diagnostics.StackFrame
static Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.StackFrames.AudienceValidationFailed -> System.Diagnostics.StackFrame
static Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.StackFrames.IssuerSigningKeyValidationFailed -> System.Diagnostics.StackFrame
static Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.StackFrames.IssuerValidationFailed -> System.Diagnostics.StackFrame
static Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.StackFrames.LifetimeValidationFailed -> System.Diagnostics.StackFrame
static Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.StackFrames.OneTimeUseValidationFailed -> System.Diagnostics.StackFrame
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,15 @@ internal async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
StackFrames.TokenValidationParametersNull);
}

var conditionsResult = ValidateConditions(samlToken, validationParameters, callContext);
ValidationResult<ValidatedConditions> conditionsResult = ValidateConditions(samlToken, validationParameters, callContext);

if (!conditionsResult.IsValid)
{
StackFrames.AssertionConditionsValidationFailed ??= new StackFrame(true);
return conditionsResult.UnwrapError().AddStackFrame(StackFrames.AssertionConditionsValidationFailed);
}

var issuerValidationResult = await validationParameters.IssuerValidatorAsync(
ValidationResult<ValidatedIssuer> issuerValidationResult = await validationParameters.IssuerValidatorAsync(
samlToken.Issuer,
samlToken,
validationParameters,
Expand All @@ -78,13 +78,27 @@ internal async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
return issuerValidationResult.UnwrapError().AddStackFrame(StackFrames.IssuerValidationFailed);
}

var signatureValidationResult = ValidateSignature(samlToken, validationParameters, callContext);
ValidationResult<SecurityKey> signatureValidationResult = ValidateSignature(samlToken, validationParameters, callContext);

if (!signatureValidationResult.IsValid)
{
StackFrames.SignatureValidationFailed ??= new StackFrame(true);
return signatureValidationResult.UnwrapError().AddStackFrame(StackFrames.SignatureValidationFailed);
}

ValidationResult<ValidatedSigningKeyLifetime> issuerSigningKeyValidationResult = validationParameters.IssuerSigningKeyValidator(
samlToken.SigningKey,
samlToken,
validationParameters,
null,
callContext);

if (!issuerSigningKeyValidationResult.IsValid)
{
StackFrames.IssuerSigningKeyValidationFailed ??= new StackFrame(true);
return issuerSigningKeyValidationResult.UnwrapError().AddStackFrame(StackFrames.IssuerSigningKeyValidationFailed);
}

return new ValidatedToken(samlToken, this, validationParameters);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ internal static class StackFrames
// Stack frames from ValidateTokenAsync using SecurityToken
internal static StackFrame? TokenNull;
internal static StackFrame? TokenValidationParametersNull;
internal static StackFrame? IssuerValidationFailed;
internal static StackFrame? IssuerSigningKeyValidationFailed;
internal static StackFrame? SignatureValidationFailed;

// Stack frames from ValidateConditions
internal static StackFrame? AudienceValidationFailed;
Expand All @@ -22,9 +25,6 @@ internal static class StackFrames
internal static StackFrame? AssertionConditionsValidationFailed;
internal static StackFrame? LifetimeValidationFailed;
internal static StackFrame? OneTimeUseValidationFailed;

internal static StackFrame? IssuerValidationFailed;
internal static StackFrame? SignatureValidationFailed;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ internal async Task<ValidationResult<ValidatedToken>> ValidateTokenAsync(
return signatureValidationResult.UnwrapError().AddStackFrame(StackFrames.SignatureValidationFailed);
}

var issuerSigningKeyValidationResult = validationParameters.IssuerSigningKeyValidator(
samlToken.SigningKey,
samlToken,
validationParameters,
null,
callContext);

if (!issuerSigningKeyValidationResult.IsValid)
{
StackFrames.IssuerSigningKeyValidationFailed ??= new StackFrame(true);
return issuerSigningKeyValidationResult.UnwrapError().AddStackFrame(StackFrames.IssuerSigningKeyValidationFailed);
}

return new ValidatedToken(samlToken, this, validationParameters);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ internal static class StackFrames
// Stack frames from ValidateTokenAsync using SecurityToken
internal static StackFrame? TokenNull;
internal static StackFrame? TokenValidationParametersNull;
internal static StackFrame? IssuerSigningKeyValidationFailed;
internal static StackFrame? IssuerValidationFailed;
internal static StackFrame? SignatureValidationFailed;

Expand Down
5 changes: 5 additions & 0 deletions src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
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
Microsoft.IdentityModel.Tokens.AlgorithmValidationError
Microsoft.IdentityModel.Tokens.AlgorithmValidationError.AlgorithmValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, string invalidAlgorithm) -> void
Microsoft.IdentityModel.Tokens.AlgorithmValidationError.InvalidAlgorithm.get -> string
Microsoft.IdentityModel.Tokens.AlgorithmValidationError._invalidAlgorithm -> string
Microsoft.IdentityModel.Tokens.AudienceValidationError.AudienceValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, Microsoft.IdentityModel.Tokens.ValidationFailureType failureType, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, System.Collections.Generic.IList<string> tokenAudiences, System.Collections.Generic.IList<string> validAudiences) -> void
Microsoft.IdentityModel.Tokens.AudienceValidationError.TokenAudiences.get -> System.Collections.Generic.IList<string>
Microsoft.IdentityModel.Tokens.IssuerValidationError.InvalidIssuer.get -> string
Microsoft.IdentityModel.Tokens.IssuerValidationError.IssuerValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, Microsoft.IdentityModel.Tokens.ValidationFailureType validationFailureType, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, string invalidIssuer, System.Exception innerException) -> void
Microsoft.IdentityModel.Tokens.IssuerValidationError.IssuerValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, string invalidIssuer, System.Exception innerException) -> void
Microsoft.IdentityModel.Tokens.IssuerValidationSource.IssuerMatchedConfiguration = 1 -> Microsoft.IdentityModel.Tokens.IssuerValidationSource
Microsoft.IdentityModel.Tokens.IssuerValidationSource.IssuerMatchedValidationParameters = 2 -> Microsoft.IdentityModel.Tokens.IssuerValidationSource
Microsoft.IdentityModel.Tokens.LifetimeValidationError._expires -> System.DateTime
Expand All @@ -31,6 +35,7 @@ static Microsoft.IdentityModel.Tokens.AudienceValidationError.ValidationParamete
static Microsoft.IdentityModel.Tokens.AudienceValidationError.ValidationParametersNull -> System.Diagnostics.StackFrame
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.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
1 change: 1 addition & 0 deletions src/Microsoft.IdentityModel.Tokens/LogMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ internal static class LogMessages
//public const string IDX10266 = "IDX10266: Unable to validate issuer. validationParameters.ValidIssuer is null or whitespace, validationParameters.ValidIssuers is null or empty and ConfigurationManager is null.";
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.";


// 10500 - SignatureValidation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,36 @@ namespace Microsoft.IdentityModel.Tokens
{
internal class IssuerValidationError : ValidationError
{
private string? _invalidIssuer;

internal IssuerValidationError(
MessageDetail messageDetail,
Type exceptionType,
StackFrame stackFrame,
string? invalidIssuer)
: base(messageDetail, ValidationFailureType.IssuerValidationFailed, exceptionType, stackFrame)
: this(messageDetail, ValidationFailureType.IssuerValidationFailed, exceptionType, stackFrame, invalidIssuer, null)
{
_invalidIssuer = invalidIssuer;
}

internal IssuerValidationError(
MessageDetail messageDetail,
ValidationFailureType validationFailureType,
Type exceptionType,
StackFrame stackFrame,
string? invalidIssuer,
Exception? innerException)
: base(messageDetail, validationFailureType, exceptionType, stackFrame, innerException)
{
InvalidIssuer = invalidIssuer;
}

internal string? InvalidIssuer { get; }

internal override Exception GetException()
{
if (ExceptionType == typeof(SecurityTokenInvalidIssuerException))
{
SecurityTokenInvalidIssuerException exception = new(MessageDetail.Message, InnerException)
{
InvalidIssuer = _invalidIssuer
InvalidIssuer = InvalidIssuer
};

return exception;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,5 +128,11 @@ private class InvalidSecurityTokenFailure : ValidationFailureType { internal Inv
/// </summary>
public static readonly ValidationFailureType XmlValidationFailed = new XmlValidationFailure("XmlValidationFailed");
private class XmlValidationFailure : ValidationFailureType { internal XmlValidationFailure(string name) : base(name) { } }

/// <summary>
/// Defines a type that represents that a token is invalid.
/// </summary>
public static readonly ValidationFailureType IssuerValidatorThrew = new IssuerValidatorFailure("IssuerValidatorThrew");
private class IssuerValidatorFailure : ValidationFailureType { internal IssuerValidatorFailure(string name) : base(name) { } }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ public IssuerSigningKeyValidationDelegate IssuerSigningKeyValidator
/// Allows overriding the delegate that will be used to validate the issuer of the token.
/// </summary>
/// <exception cref="ArgumentNullException">Thrown when the value is set as null.</exception>
/// <returns>The <see cref="IssuerValidationDelegateAsync"/> used to validate the issuer of a token</returns>
/// <returns>The <see cref="Tokens.IssuerValidationDelegateAsync"/> used to validate the issuer of a token</returns>
public IssuerValidationDelegateAsync IssuerValidatorAsync
{
get { return _issuerValidatorAsync; }
Expand Down
Loading

0 comments on commit 0409662

Please sign in to comment.