public async Task UpdateFromTemplateAsync(CallState callState)
        {
            if (!this.updatedFromTemplate)
            {
                var    authorityUri = new Uri(this.Authority);
                var    host         = authorityUri.Host;
                string path         = authorityUri.AbsolutePath.Substring(1);
                string tenant       = path.Substring(0, path.IndexOf("/", StringComparison.Ordinal));

                if (this.AuthorityType == AuthorityType.AAD)
                {
                    var metadata = await InstanceDiscovery.GetMetadataEntry(authorityUri, this.ValidateAuthority, callState);

                    host = metadata.PreferredNetwork;
                    // All the endpoints will use this updated host, and it affects future network calls, as desired.
                    // The Authority remains its original host, and will be used in TokenCache later.
                }
                else
                {
                    InstanceDiscovery.AddMetadataEntry(host);
                }
                this.AuthorizationUri      = InstanceDiscovery.FormatAuthorizeEndpoint(host, tenant);
                this.DeviceCodeUri         = string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/oauth2/devicecode", host, tenant);
                this.TokenUri              = string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/oauth2/token", host, tenant);
                this.UserRealmUri          = EnsureUrlEndsWithForwardSlash(string.Format(CultureInfo.InvariantCulture, "https://{0}/common/userrealm", host));
                this.IsTenantless          = (string.Compare(tenant, TenantlessTenantName, StringComparison.OrdinalIgnoreCase) == 0);
                this.SelfSignedJwtAudience = this.TokenUri;
                this.updatedFromTemplate   = true;
            }
        }
        public async Task TestInstanceDiscovery_WhenAuthorityIsInvalidButValidationIsNotRequired_ShouldCacheTheProvidedAuthority()
        {
            for (int i = 0; i < 2; i++) // Prepare 2 mock responses
            {
                HttpMessageHandlerFactory.AddMockHandler(new MockHttpMessageHandler(TestConstants.DefaultAuthorityHomeTenant)
                {
                    Method          = HttpMethod.Get,
                    Url             = $"https://{InstanceDiscovery.DefaultTrustedAuthority}/common/discovery/instance",
                    ResponseMessage = MockHelpers.CreateFailureResponseMessage("{\"error\":\"invalid_instance\"}")
                });
            }

            CallState callState = new CallState(Guid.NewGuid());
            string    host      = "invalid_instance.example.com";

            // ADAL still behaves correctly using developer provided authority
            var entry = await InstanceDiscovery.GetMetadataEntry(new Uri($"https://{host}/tenant"), false, callState).ConfigureAwait(false);

            Assert.AreEqual(host, entry.PreferredNetwork);                     // No exception raised, the host is returned as-is
            Assert.AreEqual(1, HttpMessageHandlerFactory.MockHandlersCount()); // 1 mock response is consumed, 1 remaining

            // Subsequent requests do not result in further authority validation network requests for the process lifetime
            var entry2 = await InstanceDiscovery.GetMetadataEntry(new Uri($"https://{host}/tenant"), false, callState).ConfigureAwait(false);

            Assert.AreEqual(host, entry2.PreferredNetwork);
            Assert.AreEqual(1, HttpMessageHandlerFactory.MockHandlersCount()); // Still 1 mock response remaining, so no new request was attempted
        }
        public void TestInstanceDiscovery_WhenMultipleSimultaneousCallsWithTheSameAuthority_ShouldMakeOnlyOneRequest()
        {
            for (int i = 0; i < 2; i++) // Prepare 2 mock responses
            {
                HttpMessageHandlerFactory.AddMockHandler(MockHelpers.CreateInstanceDiscoveryMockHandler("https://login.windows.net/common/discovery/instance"));
            }

            CallState callState = new CallState(Guid.NewGuid());
            string    host      = "login.windows.net";

            Task.WaitAll( // Simulate several simultaneous calls
                InstanceDiscovery.GetMetadataEntry(new Uri($"https://{host}/tenant"), true, callState),
                InstanceDiscovery.GetMetadataEntry(new Uri($"https://{host}/tenant"), true, callState));
            Assert.AreEqual(1, HttpMessageHandlerFactory.MockHandlersCount()); // 1 mock response is consumed, 1 remaining
        }
        public async Task TestInstanceDiscovery_WhenAuthorityIsValidAndMetadataIsReturned_ShouldCacheAllReturnedAliases()
        {
            string host = "login.windows.net";

            for (int i = 0; i < 2; i++) // Prepare 2 mock responses
            {
                HttpMessageHandlerFactory.AddMockHandler(new MockHttpMessageHandler(TestConstants.DefaultAuthorityHomeTenant)
                {
                    Method          = HttpMethod.Get,
                    Url             = $"https://{host}/common/discovery/instance",
                    ResponseMessage = new HttpResponseMessage(HttpStatusCode.OK)
                    {
                        Content = new StringContent(
                            @"{
                            ""tenant_discovery_endpoint"" : ""https://login.microsoftonline.com/v1/.well-known/openid-configuration"",
                            ""metadata"": [
                                {
                                ""preferred_network"": ""login.microsoftonline.com"",
                                ""preferred_cache"": ""login.windows.net"",
                                ""aliases"": [""login.microsoftonline.com"", ""login.windows.net"", ""sts.microsoft.com""]
                                }
                            ]
                            }"
                            )
                    }
                });
            }

            CallState callState = new CallState(Guid.NewGuid());
            // ADAL still behaves correctly using developer provided authority
            var entry = await InstanceDiscovery.GetMetadataEntry(new Uri($"https://{host}/tenant"), true, callState).ConfigureAwait(false);

            Assert.AreEqual("login.microsoftonline.com", entry.PreferredNetwork); // No exception raised, the host is returned as-is
            Assert.AreEqual(1, HttpMessageHandlerFactory.MockHandlersCount());    // 1 mock response is consumed, 1 remaining

            // Subsequent requests do not result in further authority validation network requests for the process lifetime
            var entry2 = await InstanceDiscovery.GetMetadataEntry(new Uri("https://sts.microsoft.com/tenant"), true, callState).ConfigureAwait(false);

            Assert.AreEqual("login.microsoftonline.com", entry2.PreferredNetwork);
            Assert.AreEqual(1, HttpMessageHandlerFactory.MockHandlersCount()); // Still 1 mock response remaining, so no new request was attempted
        }
        public async Task TestInstanceDiscovery_WhenAuthorityIsValidButNoMetadataIsReturned_ShouldCacheTheProvidedAuthority()
        {
            string    host      = "login.windows.net"; // A whitelisted host
            CallState callState = new CallState(Guid.NewGuid());

            for (int i = 0; i < 2; i++) // Prepare 2 mock responses
            {
                HttpMessageHandlerFactory.AddMockHandler(MockHelpers.CreateInstanceDiscoveryMockHandler(
                                                             $"https://{host}/common/discovery/instance",
                                                             @"{""tenant_discovery_endpoint"":""https://login.microsoftonline.com/tenant/.well-known/openid-configuration""}"));
            }

            // ADAL still behaves correctly using developer provided authority
            var entry = await InstanceDiscovery.GetMetadataEntry(new Uri($"https://{host}/tenant"), true, callState).ConfigureAwait(false);

            Assert.AreEqual(host, entry.PreferredNetwork);                     // No exception raised, the host is returned as-is
            Assert.AreEqual(1, HttpMessageHandlerFactory.MockHandlersCount()); // 1 mock response is consumed, 1 remaining

            // Subsequent requests do not result in further authority validation network requests for the process lifetime
            var entry2 = await InstanceDiscovery.GetMetadataEntry(new Uri($"https://{host}/tenant"), true, callState).ConfigureAwait(false);

            Assert.AreEqual(host, entry2.PreferredNetwork);
            Assert.AreEqual(1, HttpMessageHandlerFactory.MockHandlersCount()); // Still 1 mock response remaining, so no new request was attempted
        }
Exemplo n.º 6
0
        protected AcquireTokenHandlerBase(RequestData requestData)
        {
            this.Authenticator     = requestData.Authenticator;
            this.CallState         = CreateCallState(this.Authenticator.CorrelationId);
            brokerHelper.CallState = this.CallState;

            var msg = string.Format(CultureInfo.CurrentCulture,
                                    "ADAL {0} with assembly version '{1}', file version '{2}' and informational version '{3}' is running...",
                                    platformInformation.GetProductName(), AdalIdHelper.GetAdalVersion(),
                                    AdalIdHelper.GetAssemblyFileVersion(), AdalIdHelper.GetAssemblyInformationalVersion());

            CallState.Logger.Information(null, msg);
            CallState.Logger.InformationPii(null, msg);

            msg = string.Format(CultureInfo.CurrentCulture,
                                "=== Token Acquisition started: \n\tCacheType: {0}\n\tAuthentication Target: {1}\n\t",
                                tokenCache != null
                    ? tokenCache.GetType().FullName +
                                string.Format(CultureInfo.CurrentCulture, " ({0} items)", tokenCache.Count)
                    : "null",
                                requestData.SubjectType);
            if (InstanceDiscovery.IsWhitelisted(requestData.Authenticator.GetAuthorityHost()))
            {
                msg += string.Format(CultureInfo.CurrentCulture,
                                     ", Authority Host: {0}",
                                     requestData.Authenticator.GetAuthorityHost());
            }
            CallState.Logger.Information(CallState, msg);


            var piiMsg = string.Format(CultureInfo.CurrentCulture,
                                       "=== Token Acquisition started:\n\tAuthority: {0}\n\tResource: {1}\n\tClientId: {2}\n\tCacheType: {3}\n\tAuthentication Target: {4}\n\t",
                                       requestData.Authenticator.Authority, requestData.Resource, requestData.ClientKey.ClientId,
                                       (tokenCache != null)
                    ? tokenCache.GetType().FullName +
                                       string.Format(CultureInfo.CurrentCulture, " ({0} items)", tokenCache.Count)
                    : "null",
                                       requestData.SubjectType);

            CallState.Logger.InformationPii(this.CallState, piiMsg);

            this.tokenCache = requestData.TokenCache;

            if (string.IsNullOrWhiteSpace(requestData.Resource))
            {
                throw new ArgumentNullException("resource");
            }

            this.Resource         = (requestData.Resource != NullResource) ? requestData.Resource : null;
            this.ClientKey        = requestData.ClientKey;
            this.TokenSubjectType = requestData.SubjectType;

            this.LoadFromCache = (tokenCache != null);
            this.StoreToCache  = (tokenCache != null);
            this.SupportADFS   = false;

            this.brokerParameters = new Dictionary <string, string>();
            brokerParameters[BrokerParameter.Authority]     = requestData.Authenticator.Authority;
            brokerParameters[BrokerParameter.Resource]      = requestData.Resource;
            brokerParameters[BrokerParameter.ClientId]      = requestData.ClientKey.ClientId;
            brokerParameters[BrokerParameter.CorrelationId] = this.CallState.CorrelationId.ToString();

            var adalVersion = AdalIdHelper.GetAdalVersion();

            if (AdalIdHelper.VersionNotDetermined.Equals(adalVersion))
            {
                adalVersion = AdalIdHelper.GetAssemblyFileVersion();
            }
            brokerParameters[BrokerParameter.ClientVersion] = adalVersion;

            this.ResultEx = null;

            CacheQueryData.ExtendedLifeTimeEnabled = requestData.ExtendedLifeTimeEnabled;
        }