/// <summary> /// Figures out the authority based on the authority from the config and the authority from the request, /// and optionally the homeAccountTenantId, which has an impact on AcquireTokenSilent /// /// The algorithm is: /// /// 1. If there is no request authority (i.e. no authority override), use the config authority. /// 1.1. For AAD, if the config authority is "common" etc, try to use the tenanted version with the home account tenant ID /// 2. If there is a request authority, try to use it. /// 2.1. If the request authority is not "common", then use it /// 2.2 If the request authority is "common", ignore it, and use 1.1 /// /// Special cases: /// /// - if the authority is not defined at the application level and the request level is not AAD, use the request authority /// - if the authority is defined at app level, and the request level authority of is of different type, throw an exception /// /// </summary> public static async Task <Authority> CreateAuthorityForRequestAsync( RequestContext requestContext, AuthorityInfo requestAuthorityInfo, string requestHomeAccountTenantId = null) { var configAuthorityInfo = requestContext.ServiceBundle.Config.AuthorityInfo; if (configAuthorityInfo == null) { throw new ArgumentNullException(nameof(configAuthorityInfo)); } ValidateTypeMismatch(configAuthorityInfo, requestAuthorityInfo); await ValidateSameHostAsync(requestAuthorityInfo, requestContext).ConfigureAwait(false); switch (configAuthorityInfo.AuthorityType) { // ADFS and B2C are tenant-less, no need to consider tenant case AuthorityType.Adfs: return(requestAuthorityInfo == null ? new AdfsAuthority(configAuthorityInfo) : new AdfsAuthority(requestAuthorityInfo)); case AuthorityType.B2C: if (requestAuthorityInfo != null) { return(new B2CAuthority(requestAuthorityInfo)); } return(new B2CAuthority(configAuthorityInfo)); case AuthorityType.Aad: if (requestAuthorityInfo == null) { return(CreateAuthorityWithTenant(configAuthorityInfo, requestHomeAccountTenantId)); } // In case the authority is defined only at the request level if (configAuthorityInfo.IsDefaultAuthority && requestAuthorityInfo.AuthorityType != AuthorityType.Aad) { return(CreateAuthority(requestAuthorityInfo)); } var requestAuthority = new AadAuthority(requestAuthorityInfo); if (!requestAuthority.IsCommonOrganizationsOrConsumersTenant()) { return(requestAuthority); } return(CreateAuthorityWithTenant(configAuthorityInfo, requestHomeAccountTenantId)); default: throw new MsalClientException( MsalError.InvalidAuthorityType, "Unsupported authority type"); } }
/// <summary> /// Figures out the authority based on the authority from the config and the authority from the request, /// and optionally the homeAccountTenantId, which has an impact on AcquireTokenSilent /// /// The algorithm is: /// /// 1. If there is no request authority (i.e. no authority override), use the config authority. /// 1.1. For AAD, if the config authority is "common" etc, try to use the tenanted version with the home account tenant ID /// 2. If there is a request authority, try to use it. /// 2.1. If the request authority is not "common", then use it /// 2.2 If the request authority is "common", ignore it, and use 1.1 /// /// Special cases: /// /// - if the authority is not defined at the application level and the request level is not AAD, use the request authority /// - if the authority is defined at app level, and the request level authority of is of different type, throw an exception /// /// </summary> public static Authority CreateAuthorityForRequest( AuthorityInfo configAuthorityInfo, AuthorityInfo requestAuthorityInfo, string requestHomeAccountTenantId = null) { if (configAuthorityInfo == null) { throw new ArgumentNullException(nameof(configAuthorityInfo)); } ValidateTypeMismatch(configAuthorityInfo, requestAuthorityInfo); switch (configAuthorityInfo.AuthorityType) { // ADFS and B2C are tenant-less, no need to consider tenant case AuthorityType.Adfs: return(requestAuthorityInfo == null ? new AdfsAuthority(configAuthorityInfo) : new AdfsAuthority(requestAuthorityInfo)); case AuthorityType.B2C: if (requestAuthorityInfo != null) { CheckB2CAuthorityHost(requestAuthorityInfo, configAuthorityInfo); return(new B2CAuthority(requestAuthorityInfo)); } return(new B2CAuthority(configAuthorityInfo)); case AuthorityType.Aad: if (requestAuthorityInfo == null) { return(CreateAuthorityWithTenant(configAuthorityInfo, requestHomeAccountTenantId)); } // In case the authority is defined only at the request level if (configAuthorityInfo.IsDefaultAuthority && requestAuthorityInfo.AuthorityType != AuthorityType.Aad) { return(CreateAuthority(requestAuthorityInfo)); } var requestAuthority = new AadAuthority(requestAuthorityInfo); if (!requestAuthority.IsCommonOrganizationsOrConsumersTenant()) { return(requestAuthority); } return(CreateAuthorityWithTenant(configAuthorityInfo, requestHomeAccountTenantId)); default: throw new MsalClientException( MsalError.InvalidAuthorityType, "Unsupported authority type"); } }
internal override string GetTenantedAuthority(string tenantId, bool forceSpecifiedTenant = false) { if (!string.IsNullOrEmpty(tenantId) && (forceSpecifiedTenant || AadAuthority.IsCommonOrganizationsOrConsumersTenant(TenantId))) { var authorityUri = new Uri(AuthorityInfo.CanonicalAuthority); return(string.Format( CultureInfo.InvariantCulture, DstsCanonicalAuthorityTemplate, authorityUri.Authority, tenantId)); } return(AuthorityInfo.CanonicalAuthority); }
/// <inheritdoc /> public async Task <string> ValidateAuthorityAndGetOpenIdDiscoveryEndpointAsync( AuthorityInfo authorityInfo, string userPrincipalName, RequestContext requestContext) { var authorityUri = new Uri(authorityInfo.CanonicalAuthority); if (authorityInfo.ValidateAuthority && !AadAuthority.IsInTrustedHostList(authorityUri.Host)) { await _serviceBundle.AadInstanceDiscovery.GetMetadataEntryAsync( authorityUri, requestContext).ConfigureAwait(false); } return(authorityInfo.CanonicalAuthority + Constants.OpenIdConfigurationEndpoint); }
private async Task <InstanceDiscoveryResponse> SendInstanceDiscoveryRequestAsync( Uri authority, RequestContext requestContext) { var client = new OAuth2Client(_logger, _httpManager, _telemetryManager); client.AddQueryParameter("api-version", "1.1"); client.AddQueryParameter("authorization_endpoint", BuildAuthorizeEndpoint(authority.Host, GetTenant(authority))); string discoveryHost = AadAuthority.IsInTrustedHostList(authority.Host) ? authority.Host : AadAuthority.DefaultTrustedHost; string instanceDiscoveryEndpoint = BuildInstanceDiscoveryEndpoint(discoveryHost); var discoveryResponse = await client.DiscoverAadInstanceAsync(new Uri(instanceDiscoveryEndpoint), requestContext) .ConfigureAwait(false); return(discoveryResponse); }