public void AcquireTokenSilentServiceErrorTestAsync()
        {
            TokenCache    cache = new TokenCache();
            TokenCacheKey key   = new TokenCacheKey(TestConstants.DefaultAuthorityCommonTenant,
                                                    TestConstants.DefaultResource, TestConstants.DefaultClientId, TokenSubjectType.User, "unique_id",
                                                    "*****@*****.**");

            cache.tokenCacheDictionary[key] = new AuthenticationResultEx
            {
                RefreshToken       = "something-invalid",
                ResourceInResponse = TestConstants.DefaultResource,
                Result             = new AuthenticationResult("Bearer", "some-access-token", DateTimeOffset.UtcNow)
            };

            AuthenticationContext context = new AuthenticationContext(TestConstants.DefaultAuthorityCommonTenant, cache);

            var ex = AssertException.TaskThrows <AdalSilentTokenAcquisitionException>(async() =>
            {
                HttpMessageHandlerFactory.AddMockHandler(new MockHttpMessageHandler()
                {
                    Method          = HttpMethod.Post,
                    ResponseMessage = MockHelpers.CreateInvalidGrantTokenResponseMessage()
                });
                await context.AcquireTokenSilentAsync(TestConstants.DefaultResource, TestConstants.DefaultClientId, new UserIdentifier("unique_id", UserIdentifierType.UniqueId));
            });

            Assert.AreEqual(AdalError.FailedToAcquireTokenSilently, ex.ErrorCode);
            Assert.AreEqual(AdalErrorMessage.FailedToRefreshToken, ex.Message);
            Assert.IsNotNull(ex.InnerException);
            Assert.IsTrue(ex.InnerException is AdalException);
            Assert.AreEqual(((AdalException)ex.InnerException).ErrorCode, "invalid_grant");
        }
        public void OBOUserAssertionHashUsernamePassedTest()
        {
            TokenCache    cache         = TokenCacheHelper.CreateCacheWithItems();
            string        someAssertion = "some-assertion-passed-by-developer";
            TokenCacheKey key           = cache.tokenCacheDictionary.Keys.First();

            //update cache entry with hash of an assertion that will not match
            cache.tokenCacheDictionary[key].UserAssertionHash =
                new CryptographyHelper().CreateSha256Hash(someAssertion);

            ConfidentialClientApplication app = new ConfidentialClientApplication(TestConstants.DefaultClientId,
                                                                                  TestConstants.DefaultRedirectUri, new ClientCredential(TestConstants.DefaultClientSecret), new TokenCache());

            app.UserTokenCache = cache;

            //this is a fail safe. No call should go on network
            HttpMessageHandlerFactory.MockHandler = new MockHttpMessageHandler()
            {
                Method          = HttpMethod.Post,
                ResponseMessage =
                    MockHelpers.CreateInvalidGrantTokenResponseMessage()
            };

            UserAssertion assertion          = new UserAssertion(someAssertion, AssertionType, key.DisplayableId);
            Task <AuthenticationResult> task = app.AcquireTokenOnBehalfOfAsync(key.Scope.AsArray(),
                                                                               assertion, key.Authority, TestConstants.DefaultPolicy);
            AuthenticationResult result = task.Result;

            Assert.IsNotNull(result);
            Assert.AreEqual(key.UniqueId, result.User.UniqueId);
            Assert.AreEqual(key.DisplayableId, result.User.DisplayableId);
            Assert.AreEqual(HashAccessToken,
                            cache.tokenCacheDictionary[key].UserAssertionHash);
        }
Ejemplo n.º 3
0
        private async Task SilentAsync(
            PublicClientApplication app,
            ServerTokenResponse serverTokenResponse)
        {
            var account = (await app.GetAccountsAsync().ConfigureAwait(false)).Single();

            // 2 network calls - one for endpoint discovery on the tenanted authority, one to refresh the token
            if (!_instanceAndEndpointRequestPerformed)
            {
                _instanceAndEndpointRequestPerformed = true;
                _harness.HttpManager.AddInstanceDiscoveryMockHandler();
            }

            _harness.HttpManager.AddMockHandler(
                new MockHttpMessageHandler()
            {
                ExpectedMethod  = HttpMethod.Post,
                ResponseMessage =
                    IsError(serverTokenResponse) ?
                    MockHelpers.CreateInvalidGrantTokenResponseMessage(GetSubError(serverTokenResponse)) :
                    MockHelpers.CreateSuccessTokenResponseMessage(
                        TestConstants.UniqueId,
                        TestConstants.DisplayableId,
                        TestConstants.s_scope.ToArray(),
                        foci: serverTokenResponse == ServerTokenResponse.FociToken)
            });

            AuthenticationResult resultB = await app.AcquireTokenSilent(TestConstants.s_scope, account)
                                           .WithForceRefresh(true)
                                           .ExecuteAsync()
                                           .ConfigureAwait(false);

            Assert.IsNotNull(resultB.AccessToken);
            AssertAppMetadata(app, serverTokenResponse == ServerTokenResponse.FociToken);
        }
        public void AcquireTokenSilentServiceErrorTest()
        {
            PublicClientApplication app = new PublicClientApplication(TestConstants.DefaultClientId);

            app.UserTokenCache = TokenCacheHelper.CreateCacheWithItems();

            MockHttpMessageHandler mockHandler = new MockHttpMessageHandler();

            mockHandler.Method                    = HttpMethod.Post;
            mockHandler.ResponseMessage           = MockHelpers.CreateInvalidGrantTokenResponseMessage();
            HttpMessageHandlerFactory.MockHandler = mockHandler;
            try
            {
                Task <AuthenticationResult> task   = app.AcquireTokenSilentAsync(TestConstants.ScopeForAnotherResource.ToArray(), TestConstants.DefaultUniqueId);
                AuthenticationResult        result = task.Result;
                Assert.Fail("AdalSilentTokenAcquisitionException was expected");
            }
            catch (AggregateException ex)
            {
                Assert.IsNotNull(ex.InnerException);

                Assert.IsTrue(ex.InnerException is MsalSilentTokenAcquisitionException);
                var msalExc = (MsalSilentTokenAcquisitionException)ex.InnerException;
                Assert.AreEqual(MsalError.FailedToAcquireTokenSilently, msalExc.ErrorCode);
                Assert.IsNotNull(msalExc.InnerException, "MsalSilentTokenAcquisitionException inner exception is null");
                Assert.AreEqual(((MsalException)msalExc.InnerException).ErrorCode, "invalid_grant");
            }
        }
Ejemplo n.º 5
0
        private static void AddHttpMocks_BadTokenError(MockHttpManager httpManager)
        {
            httpManager.AddInstanceDiscoveryMockHandler();

            var handler = new MockHttpMessageHandler()
            {
                ExpectedMethod  = HttpMethod.Post,
                ResponseMessage = MockHelpers.CreateInvalidGrantTokenResponseMessage(MsalError.BadToken)
            };

            httpManager.AddMockHandler(handler);
        }
Ejemplo n.º 6
0
        public void AcquireTokenSilentServiceErrorTest()
        {
            PublicClientApplication app = new PublicClientApplication(TestConstants.ClientId)
            {
                ValidateAuthority = false
            };

            //add mock response for tenant endpoint discovery
            HttpMessageHandlerFactory.AddMockHandler(new MockHttpMessageHandler
            {
                Method          = HttpMethod.Get,
                ResponseMessage = MockHelpers.CreateOpenIdConfigurationResponse(TestConstants.AuthorityHomeTenant)
            });

            //populate cache
            cache = new TokenCache()
            {
                ClientId = TestConstants.ClientId
            };

            app.UserTokenCache = cache;
            TokenCacheHelper.PopulateCache(cache.TokenCacheAccessor);

            MockHttpMessageHandler mockHandler = new MockHttpMessageHandler();

            mockHandler.Method          = HttpMethod.Post;
            mockHandler.ResponseMessage = MockHelpers.CreateInvalidGrantTokenResponseMessage();
            HttpMessageHandlerFactory.AddMockHandler(mockHandler);
            try
            {
                Task <AuthenticationResult> task =
                    app.AcquireTokenSilentAsync(TestConstants.ScopeForAnotherResource.ToArray(),
                                                new User()
                {
                    DisplayableId = TestConstants.DisplayableId,
                    Identifier    = TestConstants.UserIdentifier,
                }, app.Authority, false);
                AuthenticationResult result = task.Result;
                Assert.Fail("MsalUiRequiredException was expected");
            }
            catch (AggregateException ex)
            {
                Assert.IsNotNull(ex.InnerException);
                Assert.IsTrue(ex.InnerException is MsalUiRequiredException);
                var msalExc = (MsalUiRequiredException)ex.InnerException;
                Assert.AreEqual(msalExc.ErrorCode, MsalUiRequiredException.InvalidGrantError);
            }

            Assert.IsTrue(HttpMessageHandlerFactory.IsMocksQueueEmpty, "All mocks should have been consumed");
        }
        private static void AddTokenResponse(TokenResponseType aadResponse, MockHttpManager httpManager)
        {
            switch (aadResponse)
            {
            case TokenResponseType.Valid:
                var refreshHandler = new MockHttpMessageHandler()
                {
                    ExpectedMethod  = HttpMethod.Post,
                    ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage(
                        TestConstants.UniqueId,
                        TestConstants.DisplayableId,
                        TestConstants.s_scope.ToArray())
                };
                httpManager.AddMockHandler(refreshHandler);
                break;

            case TokenResponseType.Invalid_AADUnavailable:
                var refreshHandler1 = new MockHttpMessageHandler()
                {
                    ExpectedMethod  = HttpMethod.Post,
                    ResponseMessage = MockHelpers.CreateFailureMessage(
                        System.Net.HttpStatusCode.GatewayTimeout, "gateway timeout")
                };
                var refreshHandler2 = new MockHttpMessageHandler()
                {
                    ExpectedMethod  = HttpMethod.Post,
                    ResponseMessage = MockHelpers.CreateFailureMessage(
                        System.Net.HttpStatusCode.GatewayTimeout, "gateway timeout")
                };

                // MSAL retries once for errors in the 500 - 600 range
                httpManager.AddMockHandler(refreshHandler1);
                httpManager.AddMockHandler(refreshHandler2);
                break;

            case TokenResponseType.Invalid_AADAvailable:
                var handler = new MockHttpMessageHandler()
                {
                    ExpectedMethod  = HttpMethod.Post,
                    ResponseMessage = MockHelpers.CreateInvalidGrantTokenResponseMessage()
                };

                httpManager.AddMockHandler(handler);
                break;

            default:
                throw new NotImplementedException();
            }
        }
        public void ManagedUsernameIncorrectPasswordAcquireTokenTest()
        {
            using (var httpManager = new MockHttpManager())
            {
                var serviceBundle = ServiceBundle.CreateWithCustomHttpManager(httpManager);
                httpManager.AddInstanceDiscoveryMockHandler();
                AddMockResponseforManagedAccounts(httpManager);

                var str = new SecureString();
                str.AppendChar('y');
                str.MakeReadOnly();

                httpManager.AddMockHandler(
                    new MockHttpMessageHandler
                {
                    Method          = HttpMethod.Post,
                    ResponseMessage = MockHelpers.CreateInvalidGrantTokenResponseMessage(),
                    PostDataObject  = new Dictionary <string, object>
                    {
                        { "grant_type", "password" },
                        { "username", MsalTestConstants.User.Username },
                        { "password", _secureString }
                    }
                });

                _cache.ClientId = MsalTestConstants.ClientId;
                var app = new PublicClientApplication(serviceBundle, MsalTestConstants.ClientId,
                                                      ClientApplicationBase.DefaultAuthority)
                {
                    UserTokenCache = _cache
                };

                // Call acquire token
                var result = AssertException.TaskThrows <MsalException>(
                    async() => await app.AcquireTokenByUsernamePasswordAsync(
                        MsalTestConstants.Scope,
                        MsalTestConstants.User.Username,
                        str).ConfigureAwait(false));

                // Check error code
                Assert.AreEqual(CoreErrorCodes.InvalidGrantError, result.ErrorCode);

                // There should be no cached entries.
                Assert.AreEqual(0, _cache.TokenCacheAccessor.AccessTokenCount);
            }
        }
Ejemplo n.º 9
0
        public void AcquireTokenSilentServiceErrorTest()
        {
            using (var httpManager = new MockHttpManager())
            {
                PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId)
                                              .WithAuthority(new Uri(ClientApplicationBase.DefaultAuthority), true)
                                              .WithHttpManager(httpManager)
                                              .WithTelemetry(new TraceTelemetryConfig())
                                              .BuildConcrete();
                httpManager.AddInstanceDiscoveryMockHandler();
                httpManager.AddMockHandlerForTenantEndpointDiscovery(TestConstants.AuthorityUtidTenant);

                //populate cache
                var tokenCacheHelper = new TokenCacheHelper();
                tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor);

                httpManager.AddMockHandler(
                    new MockHttpMessageHandler
                {
                    ExpectedMethod  = HttpMethod.Post,
                    ResponseMessage = MockHelpers.CreateInvalidGrantTokenResponseMessage()
                });
                try
                {
                    Task <AuthenticationResult> task = app
                                                       .AcquireTokenSilent(
                        TestConstants.s_cacheMissScope,
                        new Account(TestConstants.s_userIdentifier, TestConstants.DisplayableId, null))
                                                       .WithAuthority(app.Authority)
                                                       .WithForceRefresh(false)
                                                       .ExecuteAsync(CancellationToken.None);

                    AuthenticationResult result = task.Result;
                    Assert.Fail("MsalUiRequiredException was expected");
                }
                catch (AggregateException ex)
                {
                    Assert.IsNotNull(ex.InnerException);
                    Assert.IsTrue(ex.InnerException is MsalUiRequiredException);
                    var msalExc = (MsalUiRequiredException)ex.InnerException;
                    Assert.AreEqual(msalExc.ErrorCode, MsalError.InvalidGrantError);
                }
            }
        }
        public async Task ManagedUsernameIncorrectPasswordAcquireTokenTestAsync()
        {
            using (var httpManager = new MockHttpManager())
            {
                httpManager.AddInstanceDiscoveryMockHandler();
                AddMockResponseforManagedAccounts(httpManager);

                var str = new SecureString();
                str.AppendChar('y');
                str.MakeReadOnly();

                httpManager.AddMockHandler(
                    new MockHttpMessageHandler
                {
                    ExpectedMethod         = HttpMethod.Post,
                    ResponseMessage        = MockHelpers.CreateInvalidGrantTokenResponseMessage(),
                    ExpectedPostDataObject = new Dictionary <string, object>
                    {
                        { "grant_type", "password" },
                        { "username", TestConstants.s_user.Username },
                        { "password", _secureString }
                    }
                });

                PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId)
                                              .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs)
                                              .WithHttpManager(httpManager)
                                              .WithTelemetry(new TraceTelemetryConfig())
                                              .BuildConcrete();

                // Call acquire token
                MsalUiRequiredException result = await Assert.ThrowsExceptionAsync <MsalUiRequiredException>(
                    () => app.AcquireTokenByUsernamePassword(
                        TestConstants.s_scope,
                        TestConstants.s_user.Username,
                        str).ExecuteAsync(CancellationToken.None)).ConfigureAwait(false);

                // Check error code
                Assert.AreEqual(MsalError.InvalidGrantError, result.ErrorCode);

                // There should be no cached entries.
                Assert.AreEqual(0, app.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count());
            }
        }
Ejemplo n.º 11
0
        public async Task AuthorityMigrationTestAsync()
        {
            // make sure that for all network calls "preferred_cache" environment is used
            // (it is taken from metadata in instance discovery response),
            // except very first network call - instance discovery

            using (var httpManager = new MockHttpManager())
            {
                var authorityUri = new Uri(
                    string.Format(
                        CultureInfo.InvariantCulture,
                        "https://{0}/common",
                        TestConstants.ProductionNotPrefEnvironmentAlias));

                httpManager.AddInstanceDiscoveryMockHandler(authorityUri.AbsoluteUri);

                PublicClientApplication app = PublicClientApplicationBuilder
                                              .Create(TestConstants.ClientId)
                                              .WithAuthority(authorityUri, true)
                                              .WithHttpManager(httpManager)
                                              .WithUserTokenLegacyCachePersistenceForTest(new TestLegacyCachePersistance())
                                              .WithTelemetry(new TraceTelemetryConfig())
                                              .WithDebugLoggingCallback()
                                              .BuildConcrete();

                // mock for openId config request
                httpManager.AddMockHandler(new MockHttpMessageHandler
                {
                    ExpectedUrl = string.Format(CultureInfo.InvariantCulture, "https://{0}/common/v2.0/.well-known/openid-configuration",
                                                TestConstants.ProductionPrefNetworkEnvironment),
                    ExpectedMethod  = HttpMethod.Get,
                    ResponseMessage = MockHelpers.CreateOpenIdConfigurationResponse(TestConstants.AuthorityHomeTenant)
                });

                // mock webUi authorization
                MsalMockHelpers.ConfigureMockWebUI(
                    app.ServiceBundle.PlatformProxy,
                    AuthorizationResult.FromUri(app.AppConfig.RedirectUri + "?code=some-code"), null, TestConstants.ProductionPrefNetworkEnvironment);

                // mock token request
                httpManager.AddMockHandler(new MockHttpMessageHandler
                {
                    ExpectedUrl = string.Format(CultureInfo.InvariantCulture, "https://{0}/home/oauth2/v2.0/token",
                                                TestConstants.ProductionPrefNetworkEnvironment),
                    ExpectedMethod  = HttpMethod.Post,
                    ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage()
                });

                AuthenticationResult result = app.AcquireTokenInteractive(TestConstants.s_scope).ExecuteAsync(CancellationToken.None).Result;

                // make sure that all cache entities are stored with "preferred_cache" environment
                // (it is taken from metadata in instance discovery response)
                await ValidateCacheEntitiesEnvironmentAsync(app.UserTokenCacheInternal, TestConstants.ProductionPrefCacheEnvironment).ConfigureAwait(false);

                // silent request targeting at, should return at from cache for any environment alias
                foreach (var envAlias in TestConstants.s_prodEnvAliases)
                {
                    result = await app
                             .AcquireTokenSilent(
                        TestConstants.s_scope,
                        app.GetAccountsAsync().Result.First())
                             .WithAuthority(string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/", envAlias, TestConstants.Utid))
                             .WithForceRefresh(false)
                             .ExecuteAsync(CancellationToken.None)
                             .ConfigureAwait(false);

                    Assert.IsNotNull(result);
                }

                // mock for openId config request for tenant specific authority
                httpManager.AddMockHandler(new MockHttpMessageHandler
                {
                    ExpectedUrl = string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/v2.0/.well-known/openid-configuration",
                                                TestConstants.ProductionPrefNetworkEnvironment, TestConstants.Utid),
                    ExpectedMethod  = HttpMethod.Get,
                    ResponseMessage = MockHelpers.CreateOpenIdConfigurationResponse(TestConstants.AuthorityUtidTenant)
                });

                // silent request targeting rt should find rt in cache for authority with any environment alias
                foreach (var envAlias in TestConstants.s_prodEnvAliases)
                {
                    result = null;

                    httpManager.AddMockHandler(new MockHttpMessageHandler()
                    {
                        ExpectedUrl = string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/oauth2/v2.0/token",
                                                    TestConstants.ProductionPrefNetworkEnvironment, TestConstants.Utid),
                        ExpectedMethod   = HttpMethod.Post,
                        ExpectedPostData = new Dictionary <string, string>()
                        {
                            { "grant_type", "refresh_token" }
                        },
                        // return not retriable status code
                        ResponseMessage = MockHelpers.CreateInvalidGrantTokenResponseMessage()
                    });

                    try
                    {
                        result = await app
                                 .AcquireTokenSilent(
                            TestConstants.s_scopeForAnotherResource,
                            (await app.GetAccountsAsync().ConfigureAwait(false)).First())
                                 .WithAuthority(string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/", envAlias, TestConstants.Utid))
                                 .WithForceRefresh(false)
                                 .ExecuteAsync(CancellationToken.None).ConfigureAwait(false);
                    }
                    catch (MsalUiRequiredException)
                    {
                    }
                    catch (Exception)
                    {
                        Assert.Fail();
                    }

                    Assert.IsNull(result);
                }
            }
        }
Ejemplo n.º 12
0
        public void AuthorityMigration_IntegrationTest()
        {
            // make sure that for all network calls "preferred_cache" environment is used
            // (it is taken from metadata in instance discovery response),
            // except very first network call - instance discovery

            using (var httpManager = new MockHttpManager())
            {
                var serviceBundle = ServiceBundle.CreateWithCustomHttpManager(httpManager);
                TestInitialize(httpManager);

                PublicClientApplication app = new PublicClientApplication(
                    serviceBundle,
                    MsalTestConstants.ClientId,
                    string.Format(
                        CultureInfo.InvariantCulture,
                        "https://{0}/common",
                        MsalTestConstants.ProductionNotPrefEnvironmentAlias))
                {
                    UserTokenCache =
                    {
                        LegacyCachePersistence = new TestLegacyCachePersistance()
                    }
                };

                // mock for openId config request
                httpManager.AddMockHandler(new MockHttpMessageHandler
                {
                    Url = string.Format(CultureInfo.InvariantCulture, "https://{0}/common/v2.0/.well-known/openid-configuration",
                                        MsalTestConstants.ProductionPrefNetworkEnvironment),
                    Method          = HttpMethod.Get,
                    ResponseMessage = MockHelpers.CreateOpenIdConfigurationResponse(MsalTestConstants.AuthorityHomeTenant)
                });

                // mock webUi authorization
                MsalMockHelpers.ConfigureMockWebUI(new AuthorizationResult(AuthorizationStatus.Success,
                                                                           app.RedirectUri + "?code=some-code"), null, MsalTestConstants.ProductionPrefNetworkEnvironment);

                // mock token request
                httpManager.AddMockHandler(new MockHttpMessageHandler
                {
                    Url = string.Format(CultureInfo.InvariantCulture, "https://{0}/home/oauth2/v2.0/token",
                                        MsalTestConstants.ProductionPrefNetworkEnvironment),
                    Method          = HttpMethod.Post,
                    ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage()
                });

                AuthenticationResult result = app.AcquireTokenAsync(MsalTestConstants.Scope).Result;

                // make sure that all cache entities are stored with "preferred_cache" environment
                // (it is taken from metadata in instance discovery response)
                ValidateCacheEntitiesEnvironment(app.UserTokenCache, MsalTestConstants.ProductionPrefCacheEnvironment);

                // silent request targeting at, should return at from cache for any environment alias
                foreach (var envAlias in MsalTestConstants.ProdEnvAliases)
                {
                    result = app.AcquireTokenSilentAsync(MsalTestConstants.Scope,
                                                         app.GetAccountsAsync().Result.First(),
                                                         string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/", envAlias, MsalTestConstants.Utid),
                                                         false).Result;

                    Assert.IsNotNull(result);
                }

                // mock for openId config request for tenant spesific authority
                httpManager.AddMockHandler(new MockHttpMessageHandler
                {
                    Url = string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/v2.0/.well-known/openid-configuration",
                                        MsalTestConstants.ProductionPrefNetworkEnvironment, MsalTestConstants.Utid),
                    Method          = HttpMethod.Get,
                    ResponseMessage = MockHelpers.CreateOpenIdConfigurationResponse(MsalTestConstants.AuthorityUtidTenant)
                });

                // silent request targeting rt should find rt in cahce for authority with any environment alias
                foreach (var envAlias in MsalTestConstants.ProdEnvAliases)
                {
                    httpManager.AddMockHandler(new MockHttpMessageHandler()
                    {
                        Url = string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/oauth2/v2.0/token",
                                            MsalTestConstants.ProductionPrefNetworkEnvironment, MsalTestConstants.Utid),
                        Method   = HttpMethod.Post,
                        PostData = new Dictionary <string, string>()
                        {
                            { "grant_type", "refresh_token" }
                        },
                        // return not retriable status code
                        ResponseMessage = MockHelpers.CreateInvalidGrantTokenResponseMessage()
                    });

                    try
                    {
                        result = null;
                        result = app.AcquireTokenSilentAsync(MsalTestConstants.ScopeForAnotherResource,
                                                             app.GetAccountsAsync().Result.First(),
                                                             string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/", envAlias, MsalTestConstants.Utid),
                                                             false).Result;
                    }
                    catch (AggregateException ex)
                    {
                        Assert.IsNotNull(ex.InnerException);
                        Assert.IsTrue(ex.InnerException is MsalUiRequiredException);
                    }

                    Assert.IsNull(result);
                }
            }
        }
        public async Task AuthorityMigrationTestAsync()
        {
            // make sure that for all network calls "preferred_cache" environment is used
            // (it is taken from metadata in instance discovery response),
            // except very first network call - instance discovery

            using var harness = base.CreateTestHarness();

            var httpManager  = harness.HttpManager;
            var authorityUri = new Uri(
                string.Format(
                    CultureInfo.InvariantCulture,
                    "https://{0}/common",
                    TestConstants.ProductionNotPrefEnvironmentAlias));

            httpManager.AddInstanceDiscoveryMockHandler(authorityUri.AbsoluteUri);

            PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId)
                                          .WithAuthority(authorityUri, validateAuthority: true)
                                          .WithHttpManager(httpManager)
                                          .WithDebugLoggingCallback()
                                          .BuildConcrete();

            InMemoryTokenCache cache = new InMemoryTokenCache();

            cache.Bind(app.UserTokenCache);

            app.ServiceBundle.ConfigureMockWebUI(
                AuthorizationResult.FromUri(app.AppConfig.RedirectUri + "?code=some-code"),
                null,
                TestConstants.ProductionPrefNetworkEnvironment);

            // mock token request
            httpManager.AddMockHandler(new MockHttpMessageHandler
            {
                ExpectedUrl = string.Format(CultureInfo.InvariantCulture, "https://{0}/common/oauth2/v2.0/token",
                                            TestConstants.ProductionPrefNetworkEnvironment),
                ExpectedMethod  = HttpMethod.Post,
                ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage()
            });

            AuthenticationResult result = await app.AcquireTokenInteractive(TestConstants.s_scope).ExecuteAsync().ConfigureAwait(false);

            // make sure that all cache entities are stored with "preferred_cache" environment
            // (it is taken from metadata in instance discovery response)
            ValidateCacheEntitiesEnvironment(app.UserTokenCacheInternal, TestConstants.ProductionPrefCacheEnvironment);

            // silent request targeting at, should return at from cache for any environment alias
            foreach (var envAlias in TestConstants.s_prodEnvAliases)
            {
                var app2 = PublicClientApplicationBuilder.Create(TestConstants.ClientId)
                           .WithAuthority($"https://{envAlias}/common", validateAuthority: true)
                           .WithHttpManager(httpManager)
                           .WithDebugLoggingCallback()
                           .BuildConcrete();

                cache.Bind(app2.UserTokenCache);

                IEnumerable <IAccount> accounts = await app.GetAccountsAsync().ConfigureAwait(false);

                result = await app2.AcquireTokenSilent(TestConstants.s_scope, accounts.First())
                         .WithAuthority(string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/", envAlias, TestConstants.Utid))
                         .WithForceRefresh(false)
                         .ExecuteAsync(CancellationToken.None)
                         .ConfigureAwait(false);

                Assert.IsNotNull(result);
            }

            // silent request targeting rt should find rt in cache for authority with any environment alias
            foreach (var envAlias in TestConstants.s_prodEnvAliases)
            {
                result = null;

                httpManager.AddMockHandler(
                    new MockHttpMessageHandler
                {
                    ExpectedUrl = string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/oauth2/v2.0/token",
                                                TestConstants.ProductionPrefNetworkEnvironment, TestConstants.Utid),
                    ExpectedMethod   = HttpMethod.Post,
                    ExpectedPostData = new Dictionary <string, string>
                    {
                        { "grant_type", "refresh_token" }
                    },
                    // return not retriable status code
                    ResponseMessage = MockHelpers.CreateInvalidGrantTokenResponseMessage()
                });

                try
                {
                    var app3 = PublicClientApplicationBuilder
                               .Create(TestConstants.ClientId)
                               .WithAuthority($"https://{envAlias}/common", true)
                               .WithHttpManager(httpManager)
                               .WithDebugLoggingCallback()
                               .BuildConcrete();

                    cache.Bind(app3.UserTokenCache);

                    result = await app3
                             .AcquireTokenSilent(
                        TestConstants.s_scopeForAnotherResource,
                        (await app.GetAccountsAsync().ConfigureAwait(false)).First())
                             .WithAuthority(string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/", envAlias, TestConstants.Utid))
                             .WithForceRefresh(false)
                             .ExecuteAsync(CancellationToken.None).ConfigureAwait(false);
                }
                catch (MsalUiRequiredException)
                {
                }

                Assert.IsNull(result);
            }
        }