Skip to content
Closed
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 @@ -82,15 +82,15 @@ internal async ValueTask<TokenValidationResult> ValidateJWSAsync(
if (validationParameters.TransformBeforeSignatureValidation != null)
jsonWebToken = validationParameters.TransformBeforeSignatureValidation(jsonWebToken, validationParameters) as JsonWebToken;

if (validationParameters.SignatureValidator != null || validationParameters.SignatureValidatorUsingConfiguration != null)
if (validationParameters.SignatureValidator != null || validationParameters.SignatureValidatorUsingConfiguration != null || validationParameters.SignatureValidatorWithToken != null)
{
var validatedToken = ValidateSignatureUsingDelegates(jsonWebToken, validationParameters);
var validatedToken = ValidateSignatureUsingDelegates(jsonWebToken, validationParameters, configuration);
tokenValidationResult = await ValidateTokenPayloadAsync(
validatedToken,
Comment thread
iNinja marked this conversation as resolved.
validationParameters,
configuration).ConfigureAwait(false);

Validators.ValidateIssuerSecurityKey(validatedToken.SigningKey, validatedToken, validationParameters);
Validators.ValidateIssuerSecurityKey(validatedToken.SigningKey, validatedToken, validationParameters, configuration);
}
else
{
Expand Down Expand Up @@ -325,6 +325,50 @@ internal static bool ValidateSignature(JsonWebToken jsonWebToken, SecurityKey ke
return ValidateSignature(jsonWebToken, key, validationParameters, Telemetry.NullTelemetryClient.Instance);
}

/// <summary>
/// Validates the signature of a <see cref="JsonWebToken"/> using a single specified
/// <see cref="SecurityKey"/>.
/// </summary>
/// <param name="jsonWebToken">The <see cref="JsonWebToken"/> whose signature is to be validated.</param>
/// <param name="key">The <see cref="SecurityKey"/> to use for signature verification.</param>
/// <param name="validationParameters">The <see cref="TokenValidationParameters"/> containing
/// validation configuration, including the <see cref="CryptoProviderFactory"/> and algorithm
/// restrictions.</param>
/// <returns><see langword="true"/> if the signature is valid for the specified key;
/// otherwise, <see langword="false"/>.</returns>
/// <remarks>
/// This method is intended for use within a
/// <see cref="TokenValidationParameters.SignatureValidatorWithToken"/> or
/// <see cref="TokenValidationParameters.SignatureValidatorUsingConfiguration"/> delegate,
/// enabling the delegate to call back into the handler's signature validation logic for
/// algorithms it does not handle directly.
Comment thread
iNinja marked this conversation as resolved.
/// This method validates a single key — the caller is responsible for key resolution.
/// Argument validation errors (<see langword="null"/> parameters) throw immediately.
/// Algorithm or provider failures throw <see cref="SecurityTokenInvalidAlgorithmException"/>
/// or <see cref="InvalidOperationException"/>. A return value of <see langword="false"/>
/// indicates the cryptographic signature did not match.
/// </remarks>
/// <exception cref="SecurityTokenInvalidAlgorithmException">Thrown if the token's algorithm
/// fails algorithm validation.</exception>
/// <exception cref="InvalidOperationException">Thrown if a <see cref="SignatureProvider"/>
/// cannot be created for the key/algorithm pair.</exception>
public bool TryValidateSignature(
Comment thread
iNinja marked this conversation as resolved.
JsonWebToken jsonWebToken,
SecurityKey key,
TokenValidationParameters validationParameters)
{
if (jsonWebToken == null)
throw LogHelper.LogArgumentNullException(nameof(jsonWebToken));

if (key == null)
throw LogHelper.LogArgumentNullException(nameof(key));

if (validationParameters == null)
throw LogHelper.LogArgumentNullException(nameof(validationParameters));

return ValidateSignature(jsonWebToken, key, validationParameters, TelemetryClient);
}

private static void RecordSignatureValidationTelemetry(
Telemetry.ITelemetryClient telemetryClient,
string errorType,
Expand Down Expand Up @@ -436,12 +480,21 @@ internal static bool ValidateSignature(JsonWebToken jsonWebToken, SecurityKey ke
}
}

private static JsonWebToken ValidateSignatureUsingDelegates(JsonWebToken jsonWebToken, TokenValidationParameters validationParameters)
private static JsonWebToken ValidateSignatureUsingDelegates(JsonWebToken jsonWebToken, TokenValidationParameters validationParameters, BaseConfiguration configuration)
{
if (validationParameters.SignatureValidatorUsingConfiguration != null)
if (validationParameters.SignatureValidatorWithToken != null)
{
var validatedToken = validationParameters.SignatureValidatorWithToken(jsonWebToken, validationParameters, configuration);
if (validatedToken == null)
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSignatureException(LogHelper.FormatInvariant(TokenLogMessages.IDX10505, jsonWebToken)));

if (!(validatedToken is JsonWebToken validatedJsonWebToken))
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSignatureException(LogHelper.FormatInvariant(TokenLogMessages.IDX10506, LogHelper.MarkAsNonPII(typeof(JsonWebToken)), LogHelper.MarkAsNonPII(validatedToken.GetType()), jsonWebToken)));

return validatedJsonWebToken;
}
else if (validationParameters.SignatureValidatorUsingConfiguration != null)
{
// TODO - get configuration from validationParameters
BaseConfiguration configuration = null;
var validatedToken = validationParameters.SignatureValidatorUsingConfiguration(jsonWebToken.EncodedToken, validationParameters, configuration);
if (validatedToken == null)
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSignatureException(LogHelper.FormatInvariant(TokenLogMessages.IDX10505, jsonWebToken)));
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.DecryptTokenWithConfigurationAsync(Microsoft.IdentityModel.JsonWebTokens.JsonWebToken jwtToken, Microsoft.IdentityModel.Tokens.TokenValidationParameters validationParameters, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<string>
Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.DecryptTokenWithConfigurationAsync(Microsoft.IdentityModel.JsonWebTokens.JsonWebToken jwtToken, Microsoft.IdentityModel.Tokens.TokenValidationParameters validationParameters, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<string>
Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.TryValidateSignature(Microsoft.IdentityModel.JsonWebTokens.JsonWebToken jsonWebToken, Microsoft.IdentityModel.Tokens.SecurityKey key, Microsoft.IdentityModel.Tokens.TokenValidationParameters validationParameters) -> bool
9 changes: 9 additions & 0 deletions src/Microsoft.IdentityModel.Tokens/Delegates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ namespace Microsoft.IdentityModel.Tokens
/// <returns>The validated <see cref="SecurityToken"/>.</returns>
public delegate SecurityToken SignatureValidatorUsingConfiguration(string token, TokenValidationParameters validationParameters, BaseConfiguration configuration);

/// <summary>
/// Validates the signature of an already-parsed token using additional configuration.
/// </summary>
/// <param name="token">The parsed <see cref="SecurityToken"/>.</param>
/// <param name="validationParameters">The <see cref="TokenValidationParameters"/> to be used for validating the token.</param>
/// <param name="configuration">The configuration required for validation.</param>
/// <returns>The validated <see cref="SecurityToken"/>.</returns>
public delegate SecurityToken SignatureValidatorWithToken(SecurityToken token, TokenValidationParameters validationParameters, BaseConfiguration configuration);

/// <summary>
/// Reads the security token.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
~Microsoft.IdentityModel.Tokens.CaseSensitiveClaimsIdentity.SecurityToken.set -> void
Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken
Microsoft.IdentityModel.Tokens.TokenValidationParameters.SignatureValidatorWithToken.get -> Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken
Microsoft.IdentityModel.Tokens.TokenValidationParameters.SignatureValidatorWithToken.set -> void
~virtual Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken.Invoke(Microsoft.IdentityModel.Tokens.SecurityToken token, Microsoft.IdentityModel.Tokens.TokenValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.BaseConfiguration configuration) -> Microsoft.IdentityModel.Tokens.SecurityToken
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
~Microsoft.IdentityModel.Tokens.CaseSensitiveClaimsIdentity.SecurityToken.set -> void
Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken
Microsoft.IdentityModel.Tokens.TokenValidationParameters.SignatureValidatorWithToken.get -> Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken
Microsoft.IdentityModel.Tokens.TokenValidationParameters.SignatureValidatorWithToken.set -> void
~virtual Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken.Invoke(Microsoft.IdentityModel.Tokens.SecurityToken token, Microsoft.IdentityModel.Tokens.TokenValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.BaseConfiguration configuration) -> Microsoft.IdentityModel.Tokens.SecurityToken
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
~Microsoft.IdentityModel.Tokens.CaseSensitiveClaimsIdentity.SecurityToken.set -> void
Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken
Microsoft.IdentityModel.Tokens.TokenValidationParameters.SignatureValidatorWithToken.get -> Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken
Microsoft.IdentityModel.Tokens.TokenValidationParameters.SignatureValidatorWithToken.set -> void
~virtual Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken.Invoke(Microsoft.IdentityModel.Tokens.SecurityToken token, Microsoft.IdentityModel.Tokens.TokenValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.BaseConfiguration configuration) -> Microsoft.IdentityModel.Tokens.SecurityToken
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
~Microsoft.IdentityModel.Tokens.CaseSensitiveClaimsIdentity.SecurityToken.set -> void
Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken
Microsoft.IdentityModel.Tokens.TokenValidationParameters.SignatureValidatorWithToken.get -> Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken
Microsoft.IdentityModel.Tokens.TokenValidationParameters.SignatureValidatorWithToken.set -> void
~virtual Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken.Invoke(Microsoft.IdentityModel.Tokens.SecurityToken token, Microsoft.IdentityModel.Tokens.TokenValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.BaseConfiguration configuration) -> Microsoft.IdentityModel.Tokens.SecurityToken
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
~Microsoft.IdentityModel.Tokens.CaseSensitiveClaimsIdentity.SecurityToken.set -> void
Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken
Microsoft.IdentityModel.Tokens.TokenValidationParameters.SignatureValidatorWithToken.get -> Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken
Microsoft.IdentityModel.Tokens.TokenValidationParameters.SignatureValidatorWithToken.set -> void
~virtual Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken.Invoke(Microsoft.IdentityModel.Tokens.SecurityToken token, Microsoft.IdentityModel.Tokens.TokenValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.BaseConfiguration configuration) -> Microsoft.IdentityModel.Tokens.SecurityToken
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
~Microsoft.IdentityModel.Tokens.CaseSensitiveClaimsIdentity.SecurityToken.set -> void
Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken
Microsoft.IdentityModel.Tokens.TokenValidationParameters.SignatureValidatorWithToken.get -> Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken
Microsoft.IdentityModel.Tokens.TokenValidationParameters.SignatureValidatorWithToken.set -> void
~virtual Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken.Invoke(Microsoft.IdentityModel.Tokens.SecurityToken token, Microsoft.IdentityModel.Tokens.TokenValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.BaseConfiguration configuration) -> Microsoft.IdentityModel.Tokens.SecurityToken
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
~Microsoft.IdentityModel.Tokens.CaseSensitiveClaimsIdentity.SecurityToken.set -> void
Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken
Microsoft.IdentityModel.Tokens.TokenValidationParameters.SignatureValidatorWithToken.get -> Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken
Microsoft.IdentityModel.Tokens.TokenValidationParameters.SignatureValidatorWithToken.set -> void
~virtual Microsoft.IdentityModel.Tokens.SignatureValidatorWithToken.Invoke(Microsoft.IdentityModel.Tokens.SecurityToken token, Microsoft.IdentityModel.Tokens.TokenValidationParameters validationParameters, Microsoft.IdentityModel.Tokens.BaseConfiguration configuration) -> Microsoft.IdentityModel.Tokens.SecurityToken
13 changes: 13 additions & 0 deletions src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ protected TokenValidationParameters(TokenValidationParameters other)
SaveSigninToken = other.SaveSigninToken;
SignatureValidator = other.SignatureValidator;
SignatureValidatorUsingConfiguration = other.SignatureValidatorUsingConfiguration;
SignatureValidatorWithToken = other.SignatureValidatorWithToken;
TokenDecryptionKey = other.TokenDecryptionKey;
TokenDecryptionKeyResolver = other.TokenDecryptionKeyResolver;
TokenDecryptionKeys = other.TokenDecryptionKeys;
Expand Down Expand Up @@ -556,6 +557,18 @@ public string RoleClaimType
/// </remarks>
public SignatureValidatorUsingConfiguration SignatureValidatorUsingConfiguration { get; set; }

/// <summary>
/// Gets or sets a delegate that will be used to validate the signature of an already-parsed token,
/// using the <see cref="TokenValidationParameters"/> and the <see cref="BaseConfiguration"/>.
/// </summary>
/// <remarks>
/// If set, this delegate takes priority over <see cref="SignatureValidatorUsingConfiguration"/>
/// and <see cref="SignatureValidator"/>. Unlike those delegates, this one receives the parsed
/// <see cref="SecurityToken"/> directly, avoiding the need to re-parse the token string.
/// This delegate is only supported by <c>JsonWebTokenHandler</c>.
/// </remarks>
public SignatureValidatorWithToken SignatureValidatorWithToken { get; set; }

/// <summary>
/// Gets or sets the time provider.
/// </summary>
Expand Down
Loading