Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Establish base for ValidationParameters refactor #2709

Merged
merged 2 commits into from
Jul 15, 2024
Merged
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

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,5 @@ namespace Microsoft.IdentityModel.Tokens
{
public static partial class Validators
{
/// <summary>
/// Validates if a given algorithm for a <see cref="SecurityKey"/> is valid.
/// </summary>
/// <param name="algorithm">The algorithm to be validated.</param>
/// <param name="securityKey">The <see cref="SecurityKey"/> that signed the <see cref="SecurityToken"/>.</param>
/// <param name="securityToken">The <see cref="SecurityToken"/> being validated.</param>
/// <param name="validationParameters">The <see cref="TokenValidationParameters"/> to be used for validating the token.</param>
public static void ValidateAlgorithm(string algorithm, SecurityKey securityKey, SecurityToken securityToken, TokenValidationParameters validationParameters)
{
if (validationParameters == null)
throw LogHelper.LogArgumentNullException(nameof(validationParameters));

if (validationParameters.AlgorithmValidator != null)
{
if (!validationParameters.AlgorithmValidator(algorithm, securityKey, securityToken, validationParameters))
{
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidAlgorithmException(LogHelper.FormatInvariant(LogMessages.IDX10697, LogHelper.MarkAsNonPII(algorithm), securityKey))
{
InvalidAlgorithm = algorithm,
});
}

return;
}

if (validationParameters.ValidAlgorithms != null && validationParameters.ValidAlgorithms.Any() && !validationParameters.ValidAlgorithms.Contains(algorithm, StringComparer.Ordinal))
{
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidAlgorithmException(LogHelper.FormatInvariant(LogMessages.IDX10696, LogHelper.MarkAsNonPII(algorithm)))
{
InvalidAlgorithm = algorithm,
});
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,74 +31,6 @@ internal delegate AudienceValidationResult ValidateAudience(
/// </summary>
public static partial class Validators
{
/// <summary>
/// Determines if the audiences found in a <see cref="SecurityToken"/> are valid.
/// </summary>
/// <param name="audiences">The audiences found in the <see cref="SecurityToken"/>.</param>
/// <param name="securityToken">The <see cref="SecurityToken"/> being validated.</param>
/// <param name="validationParameters">The <see cref="TokenValidationParameters"/> to be used for validating the token.</param>
/// <exception cref="ArgumentNullException">If 'validationParameters' is null.</exception>
/// <exception cref="ArgumentNullException">If 'audiences' is null and <see cref="TokenValidationParameters.ValidateAudience"/> is true.</exception>
/// <exception cref="SecurityTokenInvalidAudienceException">If <see cref="TokenValidationParameters.ValidAudience"/> is null or whitespace and <see cref="TokenValidationParameters.ValidAudiences"/> is null.</exception>
/// <exception cref="SecurityTokenInvalidAudienceException">If none of the 'audiences' matched either <see cref="TokenValidationParameters.ValidAudience"/> or one of <see cref="TokenValidationParameters.ValidAudiences"/>.</exception>
/// <remarks>An EXACT match is required.</remarks>
public static void ValidateAudience(IEnumerable<string> audiences, SecurityToken securityToken, TokenValidationParameters validationParameters)
{
if (validationParameters == null)
throw LogHelper.LogArgumentNullException(nameof(validationParameters));

if (validationParameters.AudienceValidator != null)
{
if (!validationParameters.AudienceValidator(audiences, securityToken, validationParameters))
throw LogHelper.LogExceptionMessage(
new SecurityTokenInvalidAudienceException(
LogHelper.FormatInvariant(
LogMessages.IDX10231,
LogHelper.MarkAsUnsafeSecurityArtifact(securityToken, t => t.ToString())))
{
InvalidAudience = Utility.SerializeAsSingleCommaDelimitedString(audiences)
});

return;
}

if (!validationParameters.ValidateAudience)
{
LogHelper.LogWarning(LogMessages.IDX10233);
return;
}

if (audiences == null)
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidAudienceException(LogMessages.IDX10207) { InvalidAudience = null });

if (string.IsNullOrWhiteSpace(validationParameters.ValidAudience) && (validationParameters.ValidAudiences == null))
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidAudienceException(LogMessages.IDX10208) { InvalidAudience = Utility.SerializeAsSingleCommaDelimitedString(audiences) });

if (!audiences.Any())
throw LogHelper.LogExceptionMessage(
new SecurityTokenInvalidAudienceException(LogHelper.FormatInvariant(LogMessages.IDX10206))
{ InvalidAudience = Utility.SerializeAsSingleCommaDelimitedString(audiences) });

if (audiences is not List<string> audiencesAsList)
audiencesAsList = audiences.ToList();

if (AudienceIsValid(audiencesAsList, validationParameters))
return;

SecurityTokenInvalidAudienceException ex = new SecurityTokenInvalidAudienceException(
LogHelper.FormatInvariant(LogMessages.IDX10214,
LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(audiences)),
LogHelper.MarkAsNonPII(validationParameters.ValidAudience ?? "null"),
LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidAudiences))))
{ InvalidAudience = Utility.SerializeAsSingleCommaDelimitedString(audiences) };

if (!validationParameters.LogValidationExceptions)
throw ex;

throw LogHelper.LogExceptionMessage(ex);
}


/// <summary>
/// Determines if the audiences found in a <see cref="SecurityToken"/> are valid.
/// </summary>
Expand Down Expand Up @@ -259,13 +191,13 @@ private static bool AudiencesMatch(bool ignoreTrailingSlashWhenValidatingAudienc
{
if (validAudience.Length == tokenAudience.Length)
return string.Equals(validAudience, tokenAudience);
else if (ignoreTrailingSlashWhenValidatingAudience && AudiencesMatchIgnoringTrailingSlash(tokenAudience, validAudience))
else if (ignoreTrailingSlashWhenValidatingAudience && NewAudiencesMatchIgnoringTrailingSlash(tokenAudience, validAudience))
return true;

return false;
}

private static bool AudiencesMatchIgnoringTrailingSlash(string tokenAudience, string validAudience)
private static bool NewAudiencesMatchIgnoringTrailingSlash(string tokenAudience, string validAudience)
{
int length = -1;

Expand Down
141 changes: 0 additions & 141 deletions src/Microsoft.IdentityModel.Tokens/Validation/Validators.Issuer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,147 +32,6 @@ internal delegate Task<IssuerValidationResult> IssuerValidationDelegateAsync(
/// </summary>
public static partial class Validators
{
/// <summary>
/// Determines if an issuer found in a <see cref="SecurityToken"/> is valid.
/// </summary>
/// <param name="issuer">The issuer to validate</param>
/// <param name="securityToken">The <see cref="SecurityToken"/> that is being validated.</param>
/// <param name="validationParameters">The <see cref="TokenValidationParameters"/> to be used for validating the token.</param>
/// <returns>The issuer to use when creating the "Claim"(s) in a "ClaimsIdentity".</returns>
/// <exception cref="ArgumentNullException">If 'validationParameters' is null.</exception>
/// <exception cref="ArgumentNullException">If 'issuer' is null or whitespace and <see cref="TokenValidationParameters.ValidateIssuer"/> is true.</exception>
/// <exception cref="SecurityTokenInvalidIssuerException">If <see cref="TokenValidationParameters.ValidIssuer"/> is null or whitespace and <see cref="TokenValidationParameters.ValidIssuers"/> is null.</exception>
/// <exception cref="SecurityTokenInvalidIssuerException">If 'issuer' failed to matched either <see cref="TokenValidationParameters.ValidIssuer"/> or one of <see cref="TokenValidationParameters.ValidIssuers"/>.</exception>
/// <remarks>An EXACT match is required.</remarks>
public static string ValidateIssuer(string issuer, SecurityToken securityToken, TokenValidationParameters validationParameters)
{
return ValidateIssuer(issuer, securityToken, validationParameters, null);
}

/// <summary>
/// Determines if an issuer found in a <see cref="SecurityToken"/> is valid.
/// </summary>
/// <param name="issuer">The issuer to validate</param>
/// <param name="securityToken">The <see cref="SecurityToken"/> that is being validated.</param>
/// <param name="validationParameters">The <see cref="TokenValidationParameters"/> to be used for validating the token.</param>
/// <param name="configuration">The <see cref="BaseConfiguration"/> required for issuer and signing key validation.</param>
/// <returns>The issuer to use when creating the "Claim"(s) in a "ClaimsIdentity".</returns>
/// <exception cref="ArgumentNullException">If 'validationParameters' is null.</exception>
/// <exception cref="ArgumentNullException">If 'issuer' is null or whitespace and <see cref="TokenValidationParameters.ValidateIssuer"/> is true.</exception>
/// <exception cref="ArgumentNullException">If ' configuration' is null.</exception>
/// <exception cref="SecurityTokenInvalidIssuerException">If <see cref="TokenValidationParameters.ValidIssuer"/> is null or whitespace and <see cref="TokenValidationParameters.ValidIssuers"/> is null and <see cref="BaseConfiguration.Issuer"/> is null.</exception>
/// <exception cref="SecurityTokenInvalidIssuerException">If 'issuer' failed to matched either <see cref="TokenValidationParameters.ValidIssuer"/> or one of <see cref="TokenValidationParameters.ValidIssuers"/> or <see cref="BaseConfiguration.Issuer"/>.</exception>
/// <remarks>An EXACT match is required.</remarks>
internal static string ValidateIssuer(string issuer, SecurityToken securityToken, TokenValidationParameters validationParameters, BaseConfiguration configuration)
{
ValueTask<string> vt = ValidateIssuerAsync(issuer, securityToken, validationParameters, configuration);
return vt.IsCompletedSuccessfully ?
vt.Result :
vt.AsTask().ConfigureAwait(false).GetAwaiter().GetResult();
}

/// <summary>
/// Determines if an issuer found in a <see cref="SecurityToken"/> is valid.
/// </summary>
/// <param name="issuer">The issuer to validate</param>
/// <param name="securityToken">The <see cref="SecurityToken"/> that is being validated.</param>
/// <param name="validationParameters">The <see cref="TokenValidationParameters"/> to be used for validating the token.</param>
/// <param name="configuration">The <see cref="BaseConfiguration"/> required for issuer and signing key validation.</param>
/// <returns>The issuer to use when creating the "Claim"(s) in a "ClaimsIdentity".</returns>
/// <exception cref="ArgumentNullException">If 'validationParameters' is null.</exception>
/// <exception cref="ArgumentNullException">If 'issuer' is null or whitespace and <see cref="TokenValidationParameters.ValidateIssuer"/> is true.</exception>
/// <exception cref="ArgumentNullException">If ' configuration' is null.</exception>
/// <exception cref="SecurityTokenInvalidIssuerException">If <see cref="TokenValidationParameters.ValidIssuer"/> is null or whitespace and <see cref="TokenValidationParameters.ValidIssuers"/> is null and <see cref="BaseConfiguration.Issuer"/> is null.</exception>
/// <exception cref="SecurityTokenInvalidIssuerException">If 'issuer' failed to matched either <see cref="TokenValidationParameters.ValidIssuer"/> or one of <see cref="TokenValidationParameters.ValidIssuers"/> or <see cref="BaseConfiguration.Issuer"/>.</exception>
/// <remarks>An EXACT match is required.</remarks>
internal static async ValueTask<string> ValidateIssuerAsync(
string issuer,
SecurityToken securityToken,
TokenValidationParameters validationParameters,
BaseConfiguration configuration)
{
if (validationParameters == null)
throw LogHelper.LogArgumentNullException(nameof(validationParameters));

if (validationParameters.IssuerValidatorAsync != null)
return await validationParameters.IssuerValidatorAsync(issuer, securityToken, validationParameters).ConfigureAwait(false);

if (validationParameters.IssuerValidatorUsingConfiguration != null)
return validationParameters.IssuerValidatorUsingConfiguration(issuer, securityToken, validationParameters, configuration);

if (validationParameters.IssuerValidator != null)
return validationParameters.IssuerValidator(issuer, securityToken, validationParameters);

if (!validationParameters.ValidateIssuer)
{
LogHelper.LogWarning(LogMessages.IDX10235);
return issuer;
}

if (string.IsNullOrWhiteSpace(issuer))
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidIssuerException(LogMessages.IDX10211)
{ InvalidIssuer = issuer });

// Throw if all possible places to validate against are null or empty
if (string.IsNullOrWhiteSpace(validationParameters.ValidIssuer)
&& validationParameters.ValidIssuers.IsNullOrEmpty()
&& string.IsNullOrWhiteSpace(configuration?.Issuer))
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidIssuerException(LogMessages.IDX10204)
{ InvalidIssuer = issuer });

if (configuration != null)
{
if (string.Equals(configuration.Issuer, issuer))
{
if (LogHelper.IsEnabled(EventLogLevel.Informational))
LogHelper.LogInformation(LogMessages.IDX10236, LogHelper.MarkAsNonPII(issuer));

return issuer;
}
}

if (string.Equals(validationParameters.ValidIssuer, issuer))
{
if (LogHelper.IsEnabled(EventLogLevel.Informational))
LogHelper.LogInformation(LogMessages.IDX10236, LogHelper.MarkAsNonPII(issuer));

return issuer;
}

if (validationParameters.ValidIssuers != null)
{
foreach (string str in validationParameters.ValidIssuers)
{
if (string.IsNullOrEmpty(str))
{
LogHelper.LogInformation(LogMessages.IDX10262);
continue;
}

if (string.Equals(str, issuer))
{
if (LogHelper.IsEnabled(EventLogLevel.Informational))
LogHelper.LogInformation(LogMessages.IDX10236, LogHelper.MarkAsNonPII(issuer));

return issuer;
}
}
}

SecurityTokenInvalidIssuerException ex = new SecurityTokenInvalidIssuerException(
LogHelper.FormatInvariant(LogMessages.IDX10205,
LogHelper.MarkAsNonPII(issuer),
LogHelper.MarkAsNonPII(validationParameters.ValidIssuer ?? "null"),
LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidIssuers)),
LogHelper.MarkAsNonPII(configuration?.Issuer)))
{ InvalidIssuer = issuer };

if (!validationParameters.LogValidationExceptions)
throw ex;

throw LogHelper.LogExceptionMessage(ex);
}

/// <summary>
/// Determines if an issuer found in a <see cref="SecurityToken"/> is valid.
/// </summary>
Expand Down
Loading