Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion src/Microsoft.IdentityModel.Tokens/LogMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ internal static class LogMessages
public const string IDX10208 = "IDX10208: Unable to validate audience. validationParameters.ValidAudience is null or whitespace and validationParameters.ValidAudiences is null.";
public const string IDX10209 = "IDX10209: Token has length: '{0}' which is larger than the MaximumTokenSizeInBytes: '{1}'.";
public const string IDX10211 = "IDX10211: Unable to validate issuer. The 'issuer' parameter is null or whitespace.";
public const string IDX10214 = "IDX10214: Audience validation failed. Audiences: '{0}'. Did not match: validationParameters.ValidAudience: '{1}' or validationParameters.ValidAudiences: '{2}'.";
public const string IDX10214 = "IDX10214: Audience validation failed. Audiences: '{0}'. Did not match: validationParameters.ValidAudiences: '{1}'.";
public const string IDX10222 = "IDX10222: Lifetime validation failed. The token is not yet valid. ValidFrom (UTC): '{0}', Current time (UTC): '{1}'.";
public const string IDX10223 = "IDX10223: Lifetime validation failed. The token is expired. ValidTo (UTC): '{0}', Current time (UTC): '{1}'.";
public const string IDX10224 = "IDX10224: Lifetime validation failed. The NotBefore (UTC): '{0}' is after Expires (UTC): '{1}'.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ internal class ValidationParameters
private string _roleClaimType = ClaimsIdentity.DefaultRoleClaimType;
private Dictionary<string, object> _instancePropertyBag;
private IList<string> _validTokenTypes = [];
private IList<string> _validAudiences = [];

private AlgorithmValidatorDelegate _algorithmValidator = Validators.ValidateAlgorithm;
private AudienceValidatorDelegate _audienceValidator = Validators.ValidateAudience;
Expand Down Expand Up @@ -513,9 +514,14 @@ public TypeValidatorDelegate TypeValidator

/// <summary>
/// Gets the <see cref="IList{String}"/> that contains valid audiences that will be used to check against the token's audience.
/// The default is <c>null</c>.
/// The default is an empty collection.
/// </summary>
public IList<string> ValidAudiences { get; }
/// <exception cref="ArgumentNullException">Thrown when the value is set as null.</exception>
public IList<string> ValidAudiences
{
get { return _validAudiences; }
set { _validAudiences = value ?? throw new ArgumentNullException(nameof(value), "ValidAudiences cannot be set as null."); }
}

/// <summary>
/// Gets the <see cref="IList{String}"/> that contains valid issuers that will be used to check against the token's issuer.
Expand All @@ -533,14 +539,8 @@ public TypeValidatorDelegate TypeValidator
/// <returns>The <see cref="IList{String}"/> that contains valid token types that will be used to check against the token's 'typ' claim.</returns>
public IList<string> ValidTypes
{
get
{
return _validTokenTypes;
}
set
{
_validTokenTypes = value ?? throw new ArgumentNullException(nameof(value));
}
get { return _validTokenTypes; }
set { _validTokenTypes = value ?? throw new ArgumentNullException(nameof(value), "ValidTypes cannot be set as null."); }
}

public bool ValidateActor { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ namespace Microsoft.IdentityModel.Tokens
/// <returns>A <see cref="IssuerValidationResult"/>that contains the results of validating the issuer.</returns>
/// <remarks>This delegate is not expected to throw.</remarks>
internal delegate AudienceValidationResult AudienceValidatorDelegate(
IEnumerable<string> audiences,
IList<string> audiences,
SecurityToken? securityToken,
TokenValidationParameters validationParameters,
ValidationParameters validationParameters,
CallContext callContext);

/// <summary>
Expand All @@ -44,7 +44,7 @@ public static partial class Validators
/// <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>
#pragma warning disable CA1801 // TODO: remove pragma disable once callContext is used for logging
internal static AudienceValidationResult ValidateAudience(IEnumerable<string> audiences, SecurityToken? securityToken, TokenValidationParameters validationParameters, CallContext callContext)
internal static AudienceValidationResult ValidateAudience(IList<string> audiences, SecurityToken? securityToken, ValidationParameters validationParameters, CallContext callContext)
#pragma warning restore CA1801
{
if (validationParameters == null)
Expand All @@ -58,12 +58,6 @@ internal static AudienceValidationResult ValidateAudience(IEnumerable<string> au
typeof(ArgumentNullException),
new StackFrame(true)));

if (!validationParameters.ValidateAudience)
{
LogHelper.LogWarning(LogMessages.IDX10233);
return new AudienceValidationResult(Utility.SerializeAsSingleCommaDelimitedString(audiences));
}

if (audiences == null)
return new AudienceValidationResult(
Utility.SerializeAsSingleCommaDelimitedString(audiences),
Expand All @@ -75,92 +69,45 @@ internal static AudienceValidationResult ValidateAudience(IEnumerable<string> au
typeof(SecurityTokenInvalidAudienceException),
new StackFrame(true)));

if (string.IsNullOrWhiteSpace(validationParameters.ValidAudience) && (validationParameters.ValidAudiences == null))
if (audiences.Count == 0)
return new AudienceValidationResult(
Utility.SerializeAsSingleCommaDelimitedString(audiences),
ValidationFailureType.NullArgument,
new ExceptionDetail(
new MessageDetail(
LogMessages.IDX10208,
null),
typeof(SecurityTokenInvalidAudienceException),
new StackFrame(true)));

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

if (audiencesAsList.Count == 0)
return new AudienceValidationResult(
Utility.SerializeAsSingleCommaDelimitedString(audiencesAsList),
ValidationFailureType.NullArgument,
new ExceptionDetail(
new MessageDetail(
LogMessages.IDX10206,
null),
typeof(SecurityTokenInvalidAudienceException),
new StackFrame(true)));

string? validAudience = AudienceIsValidReturning(audiencesAsList, validationParameters);
string? validAudience = AudienceIsValidReturning((List<string>)audiences, validationParameters);
if (validAudience != null)
{
return new AudienceValidationResult(validAudience);
}

return new AudienceValidationResult(
Utility.SerializeAsSingleCommaDelimitedString(audiencesAsList),
Utility.SerializeAsSingleCommaDelimitedString(audiences),
ValidationFailureType.AudienceValidationFailed,
new ExceptionDetail(
new MessageDetail(
LogMessages.IDX10214,
LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(audiencesAsList)),
LogHelper.MarkAsNonPII(validationParameters.ValidAudience ?? "null"),
LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(audiences)),
LogHelper.MarkAsNonPII(Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidAudiences))),
typeof(SecurityTokenInvalidAudienceException),
new StackFrame(true)));
}

private static bool AudienceIsValid(List<string> audiences, TokenValidationParameters validationParameters)
{
return AudienceIsValidReturning(audiences, validationParameters) != null;
}

private static string? AudienceIsValidReturning(List<string> audiences, TokenValidationParameters validationParameters)
private static string? AudienceIsValidReturning(List<string> audiences, ValidationParameters validationParameters)
{
string? validAudience = null;
if (!string.IsNullOrWhiteSpace(validationParameters.ValidAudience))
validAudience = AudiencesMatchSingle(audiences, validationParameters.ValidAudience, validationParameters.IgnoreTrailingSlashWhenValidatingAudience);

if (validAudience == null && validationParameters.ValidAudiences != null)
{
if (validationParameters.ValidAudiences is not List<string> validAudiences)
validAudiences = validationParameters.ValidAudiences.ToList();

validAudience = AudiencesMatchList(audiences, validAudiences, validationParameters.IgnoreTrailingSlashWhenValidatingAudience);
}
List<string> validAudiences = validationParameters.ValidAudiences.ToList();
validAudience = AudiencesMatchList(audiences, validAudiences, validationParameters.IgnoreTrailingSlashWhenValidatingAudience);

return validAudience;
}

private static string? AudiencesMatchSingle(List<string> audiences, string validAudience, bool ignoreTrailingSlashWhenValidatingAudience)
{
for (int i = 0; i < audiences.Count; i++)
{
string tokenAudience = audiences[i];
if (string.IsNullOrWhiteSpace(tokenAudience))
continue;

if (AudiencesMatch(ignoreTrailingSlashWhenValidatingAudience, tokenAudience, validAudience))
{
if (LogHelper.IsEnabled(EventLogLevel.Informational))
LogHelper.LogInformation(LogMessages.IDX10234, LogHelper.MarkAsNonPII(tokenAudience));

return tokenAudience;
}
}

return null;
}

private static string? AudiencesMatchList(IList<string> audiences, List<string> validAudiences, bool ignoreTrailingSlashWhenValidatingAudience)
{
for (int i = 0; i < audiences.Count; i++)
Expand Down
Loading