Skip to content

Commit

Permalink
rename new validator to old validator name
Browse files Browse the repository at this point in the history
  • Loading branch information
jennyf19 committed Jun 5, 2021
1 parent fd57c09 commit e999c8a
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 372 deletions.
48 changes: 4 additions & 44 deletions src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

114 changes: 76 additions & 38 deletions src/Microsoft.Identity.Web/Resource/AadIssuerValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,38 @@
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http;
using Microsoft.Extensions.Options;
using Microsoft.Identity.Web.InstanceDiscovery;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Tokens;

namespace Microsoft.Identity.Web.Resource
{
/// <summary>
/// Generic class that validates token issuer from the provided Azure AD authority.
/// </summary>
[Obsolete(IDWebErrorMessage.AadIssuerValidatorIsObsolete, false)]
public class AadIssuerValidator
{
/// <summary>
/// A list of all Issuers across the various Azure AD instances.
/// </summary>
private readonly ISet<string> _issuerAliases;

internal /*internal for tests*/ AadIssuerValidator(IEnumerable<string> aliases)
internal AadIssuerValidator(
IOptions<AadIssuerValidatorOptions> aadIssuerValidatorOptions,
IHttpClientFactory httpClientFactory,
string aadAuthority)
{
_issuerAliases = new HashSet<string>(aliases, StringComparer.OrdinalIgnoreCase);
AadIssuerValidatorOptions = aadIssuerValidatorOptions;
HttpClientFactory = httpClientFactory;
AadAuthority = aadAuthority.TrimEnd('/');
}

private IOptions<AadIssuerValidatorOptions> AadIssuerValidatorOptions { get; }
private IHttpClientFactory HttpClientFactory { get; }
internal string? AadIssuerV1 { get; set; }
internal string? AadIssuerV2 { get; set; }
internal string AadAuthority { get; set; }

/// <summary>
/// Validate the issuer for multi-tenant applications of various audiences (Work and School accounts, or Work and School accounts +
/// Personal accounts).
Expand All @@ -35,8 +43,7 @@ public class AadIssuerValidator
/// <param name="validationParameters">Token validation parameters.</param>
/// <remarks>The issuer is considered as valid if it has the same HTTP scheme and authority as the
/// authority from the configuration file, has a tenant ID, and optionally v2.0 (this web API
/// accepts both V1 and V2 tokens).
/// Authority aliasing is also taken into account.</remarks>
/// accepts both V1 and V2 tokens).</remarks>
/// <returns>The <c>issuer</c> if it's valid, or otherwise <c>SecurityTokenInvalidIssuerException</c> is thrown.</returns>
/// <exception cref="ArgumentNullException"> if <paramref name="securityToken"/> is null.</exception>
/// <exception cref="ArgumentNullException"> if <paramref name="validationParameters"/> is null.</exception>
Expand Down Expand Up @@ -67,6 +74,38 @@ public string Validate(
throw new SecurityTokenInvalidIssuerException(IDWebErrorMessage.TenantIdClaimNotPresentInToken);
}

if (validationParameters.ValidIssuers == null && validationParameters.ValidIssuer == null)
{
if (securityToken.Issuer.EndsWith("v2.0"))
{
if (AadIssuerV2 == null)
{
IssuerMetadata issuerMetadata =
CreateConfigManager(AadAuthority).GetConfigurationAsync().ConfigureAwait(false).GetAwaiter().GetResult();
AadIssuerV2 = issuerMetadata.Issuer!;
}

if (IsValidIssuer(AadIssuerV2, tenantId, actualIssuer))
{
return actualIssuer;
}
}
else
{
if (AadIssuerV1 == null)
{
IssuerMetadata issuerMetadata =
CreateConfigManager(AadAuthority.Replace("/v2.0", string.Empty)).GetConfigurationAsync().ConfigureAwait(false).GetAwaiter().GetResult();
AadIssuerV1 = issuerMetadata.Issuer!;
}

if (IsValidIssuer(AadIssuerV1, tenantId, actualIssuer))
{
return actualIssuer;
}
}
}

if (validationParameters.ValidIssuers != null)
{
foreach (var validIssuerTemplate in validationParameters.ValidIssuers)
Expand All @@ -78,9 +117,12 @@ public string Validate(
}
}

if (IsValidIssuer(validationParameters.ValidIssuer, tenantId, actualIssuer))
if (validationParameters.ValidIssuer != null)
{
return actualIssuer;
if (IsValidIssuer(validationParameters.ValidIssuer, tenantId, actualIssuer))
{
return actualIssuer;
}
}

// If a valid issuer is not found, throw
Expand All @@ -91,6 +133,26 @@ public string Validate(
actualIssuer));
}

private ConfigurationManager<IssuerMetadata> CreateConfigManager(
string aadAuthority)
{
if (AadIssuerValidatorOptions?.Value?.HttpClientName != null && HttpClientFactory != null)
{
return
new ConfigurationManager<IssuerMetadata>(
$"{aadAuthority}{Constants.OidcEndpoint}",
new IssuerConfigurationRetriever(),
HttpClientFactory.CreateClient(AadIssuerValidatorOptions.Value.HttpClientName));
}
else
{
return
new ConfigurationManager<IssuerMetadata>(
$"{aadAuthority}{Constants.OidcEndpoint}",
new IssuerConfigurationRetriever());
}
}

private bool IsValidIssuer(string validIssuerTemplate, string tenantId, string actualIssuer)
{
if (string.IsNullOrEmpty(validIssuerTemplate))
Expand All @@ -103,14 +165,7 @@ private bool IsValidIssuer(string validIssuerTemplate, string tenantId, string a
Uri issuerFromTemplateUri = new Uri(validIssuerTemplate.Replace("{tenantid}", tenantId));
Uri actualIssuerUri = new Uri(actualIssuer);

// Template authority is in the aliases
return _issuerAliases.Contains(issuerFromTemplateUri.Authority) &&
// "iss" authority is in the aliases
_issuerAliases.Contains(actualIssuerUri.Authority) &&
// Template authority ends in the tenant ID
IsValidTidInLocalPath(tenantId, issuerFromTemplateUri) &&
// "iss" ends in the tenant ID
IsValidTidInLocalPath(tenantId, actualIssuerUri);
return issuerFromTemplateUri.AbsoluteUri == actualIssuerUri.AbsoluteUri;
}
catch
{
Expand All @@ -120,12 +175,6 @@ private bool IsValidIssuer(string validIssuerTemplate, string tenantId, string a
return false;
}

private static bool IsValidTidInLocalPath(string tenantId, Uri uri)
{
string trimmedLocalPath = uri.LocalPath.Trim('/');
return trimmedLocalPath == tenantId || trimmedLocalPath == $"{tenantId}/v2.0";
}

/// <summary>Gets the tenant ID from a token.</summary>
/// <param name="securityToken">A JWT token.</param>
/// <returns>A string containing the tenant ID, if found or <see cref="string.Empty"/>.</returns>
Expand Down Expand Up @@ -196,16 +245,5 @@ private static string GetTenantIdFromIss(string iss)

return string.Empty;
}

/// <summary>
/// This method is now Obsolete.
/// </summary>
/// <param name="aadAuthority">Aad authority.</param>
/// <returns>NotImplementedException.</returns>
[Obsolete(IDWebErrorMessage.AadIssuerValidatorGetIssuerValidatorIsObsolete, true)]
public static AadIssuerValidator GetIssuerValidator(string aadAuthority)
{
throw new NotImplementedException(IDWebErrorMessage.AadIssuerValidatorGetIssuerValidatorIsObsolete);
}
}
}
Loading

0 comments on commit e999c8a

Please sign in to comment.