public async Task FailingTest_ListenerTimesOut_Async()
        {
            var pca = PublicClientApplicationBuilder
                      .Create("1d18b3b0-251b-4714-a02a-9956cec86c2d")
                      .WithRedirectUri(SeleniumWebUI.FindFreeLocalhostRedirectUri())
                      .WithTestLogging()
                      .Build();

            // The timeout is greater than the timeout of the TCP listener
            var seleniumLogic = new SeleniumWebUI((driver) =>
            {
                Trace.WriteLine("Doing nothing for while, until the TCP listener times out");
                Task.Delay(TimeSpan.FromSeconds(3));
            }, TestContext);

            // The exception propagated to the test should be Selenium exception,
            // the test should not wait for the TCP listener to time out
            var ex = await AssertException.TaskThrowsAsync <MsalClientException>(() => pca
                                                                                 .AcquireTokenInteractive(s_scopes)
                                                                                 .WithCustomWebUi(seleniumLogic)
                                                                                 .ExecuteAsync(new CancellationTokenSource(TimeSpan.FromSeconds(2)).Token))
                     .ConfigureAwait(false);

            // TODO: CustomWebUI uses an MSAL exception for cancellation, however this
            // breaks the CancellationToken cancellation semantics, which state that
            // the listener (i.e. CustomWebUI) should throw OperationCancelledException
            Assert.AreEqual(MsalError.AuthenticationCanceledError, ex.ErrorCode);
        }
コード例 #2
0
        public async Task ValidateCcsHeadersForInteractiveAuthCodeFlowAsync()
        {
            HttpSnifferClientFactory factory = null;
            LabResponse labResponse          = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false);

            var pca = PublicClientApplicationBuilder
                      .Create(labResponse.App.AppId)
                      .WithDefaultRedirectUri()
                      .WithRedirectUri(SeleniumWebUI.FindFreeLocalhostRedirectUri())
                      .WithTestLogging(out factory)
                      .Build();

            AuthenticationResult authResult = await pca
                                              .AcquireTokenInteractive(s_scopes)
                                              .WithPrompt(Prompt.SelectAccount)
                                              .WithCustomWebUi(CreateSeleniumCustomWebUI(labResponse.User, Prompt.SelectAccount))
                                              .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token)
                                              .ConfigureAwait(false);


            var CcsHeader    = TestCommon.GetCcsHeaderFromSnifferFactory(factory);
            var userObjectId = labResponse.User.ObjectId;
            var userTenantID = labResponse.User.TenantId;

            Assert.AreEqual($"X-AnchorMailbox:Oid:{userObjectId}@{userTenantID}", $"{CcsHeader.Key}:{CcsHeader.Value.FirstOrDefault()}");

            Assert.IsNotNull(authResult);
            Assert.IsNotNull(authResult.AccessToken);
        }
コード例 #3
0
        private async Task RunPromptTestForUserAsync(LabResponse labResponse, Prompt prompt, bool useLoginHint)
        {
            var pca = PublicClientApplicationBuilder
                      .Create(labResponse.App.AppId)
                      .WithDefaultRedirectUri()
                      .WithRedirectUri(SeleniumWebUI.FindFreeLocalhostRedirectUri())
                      .WithTestLogging()
                      .Build();

            AcquireTokenInteractiveParameterBuilder builder = pca
                                                              .AcquireTokenInteractive(s_scopes)
                                                              .WithPrompt(prompt)
                                                              .WithCustomWebUi(CreateSeleniumCustomWebUI(labResponse.User, prompt, useLoginHint));

            if (useLoginHint)
            {
                builder = builder.WithLoginHint(labResponse.User.Upn);
            }

            AuthenticationResult result = await builder
                                          .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token)
                                          .ConfigureAwait(false);

            await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false);
        }
        private async Task <AuthenticationResult> RunTestForUserAsync(LabResponse labResponse, bool directToAdfs = false)
        {
            IPublicClientApplication pca;

            if (directToAdfs)
            {
                pca = PublicClientApplicationBuilder
                      .Create(Adfs2019LabConstants.PublicClientId)
                      .WithRedirectUri(Adfs2019LabConstants.ClientRedirectUri)
                      .WithAdfsAuthority(Adfs2019LabConstants.Authority)
                      .BuildConcrete();
            }
            else
            {
                pca = PublicClientApplicationBuilder
                      .Create(labResponse.AppId)
                      .WithRedirectUri(SeleniumWebUI.FindFreeLocalhostRedirectUri())
                      .Build();
            }
            Trace.WriteLine("Part 1 - Acquire a token interactively, no login hint");
            AuthenticationResult result = await pca
                                          .AcquireTokenInteractive(s_scopes)
                                          .WithCustomWebUi(CreateSeleniumCustomWebUI(labResponse.User, Prompt.SelectAccount, false, directToAdfs))
                                          .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token)
                                          .ConfigureAwait(false);

            IAccount account = await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false);

            Trace.WriteLine("Part 2 - Clear the cache");
            await pca.RemoveAsync(account).ConfigureAwait(false);

            Assert.IsFalse((await pca.GetAccountsAsync().ConfigureAwait(false)).Any());

            Trace.WriteLine("Part 3 - Acquire a token interactively again, with login hint");
            result = await pca
                     .AcquireTokenInteractive(s_scopes)
                     .WithCustomWebUi(CreateSeleniumCustomWebUI(labResponse.User, Prompt.ForceLogin, true, directToAdfs))
                     .WithPrompt(Prompt.ForceLogin)
                     .WithLoginHint(labResponse.User.HomeUPN)
                     .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token)
                     .ConfigureAwait(false);

            account = await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false);

            Trace.WriteLine("Part 4 - Acquire a token silently");
            result = await pca
                     .AcquireTokenSilent(s_scopes, account)
                     .ExecuteAsync(CancellationToken.None)
                     .ConfigureAwait(false);

            await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false);

            return(result);
        }
コード例 #5
0
        public async Task Interactive_SSHCert_Async()
        {
            LabResponse labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false);

            IPublicClientApplication pca = PublicClientApplicationBuilder
                                           .Create(labResponse.AppId)
                                           .WithRedirectUri(SeleniumWebUI.FindFreeLocalhostRedirectUri())
                                           .Build();

            TokenCacheAccessRecorder userCacheAccess = pca.UserTokenCache.RecordAccess();

            Trace.WriteLine("Part 1 - Acquire an SSH cert interactively ");
            string jwk = CreateJwk();

            AuthenticationResult result = await pca
                                          .AcquireTokenInteractive(s_scopes)
                                          .WithCustomWebUi(CreateSeleniumCustomWebUI(labResponse.User, Prompt.ForceLogin))
                                          .WithSSHCertificateAuthenticationScheme(jwk, "key1")
                                          .WithExtraQueryParameters(GetTestSliceParams()) // TODO: remove this once feature is in PROD
                                          .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token)
                                          .ConfigureAwait(false);

            userCacheAccess.AssertAccessCounts(0, 1);
            Assert.AreEqual("ssh-cert", result.TokenType);
            IAccount account = await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false);

            userCacheAccess.AssertAccessCounts(1, 1); // the assert calls GetAccounts

            Trace.WriteLine("Part 2 - Acquire a token silent with the same keyID - should be served from the cache");
            result = await pca
                     .AcquireTokenSilent(s_scopes, account)
                     .WithSSHCertificateAuthenticationScheme(jwk, "key1")
                     .WithExtraQueryParameters(GetTestSliceParams()) // TODO: remove this once feature is in PROD
                     .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token)
                     .ConfigureAwait(false);

            userCacheAccess.AssertAccessCounts(2, 1);

            account = await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false);

            userCacheAccess.AssertAccessCounts(3, 1);

            Trace.WriteLine("Part 3 - Acquire a token silent with a different keyID - should not sbe served from the cache");
            result = await pca
                     .AcquireTokenSilent(s_scopes, account)
                     .WithSSHCertificateAuthenticationScheme(jwk, "key2")
                     .WithExtraQueryParameters(GetTestSliceParams()) // TODO: remove this once feature is in PROD
                     .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token)
                     .ConfigureAwait(false);

            Assert.AreEqual("ssh-cert", result.TokenType);
            userCacheAccess.AssertAccessCounts(4, 2);
            await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false);
        }
コード例 #6
0
        public async Task Interactive_Arlington_MultiCloudSupport_AADAsync()
        {
            // Arrange
            LabResponse labResponse = await LabUserHelper.GetArlingtonUserAsync().ConfigureAwait(false);

            IPublicClientApplication pca = PublicClientApplicationBuilder
                                           .Create(labResponse.App.AppId)
                                           .WithRedirectUri(SeleniumWebUI.FindFreeLocalhostRedirectUri())
                                           .WithAuthority("https://login.microsoftonline.com/common")
                                           .WithMultiCloudSupport(true)
                                           .WithTestLogging()
                                           .Build();

            Trace.WriteLine("Part 1 - Acquire a token interactively");
            AuthenticationResult result = await pca
                                          .AcquireTokenInteractive(s_scopes)
                                          .WithCustomWebUi(CreateSeleniumCustomWebUI(labResponse.User, Prompt.SelectAccount, false))
                                          .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token)
                                          .ConfigureAwait(false);

            Assert.IsNotNull(result);
            Assert.IsNotNull(result.Account);
            Assert.IsNotNull(result.Account.GetTenantProfiles());
            Assert.IsTrue(result.Account.GetTenantProfiles().Any());
            Assert.AreEqual(labResponse.User.Upn, result.Account.Username);
            Assert.IsTrue(labResponse.Lab.Authority.Contains(result.Account.Environment));

            Trace.WriteLine("Part 2 - Get Accounts");
            var accounts = await pca.GetAccountsAsync().ConfigureAwait(false);

            Assert.IsNotNull(accounts);
            Assert.IsNotNull(accounts.Single());

            var account = accounts.Single();

            Assert.IsNotNull(account.GetTenantProfiles());
            Assert.IsTrue(account.GetTenantProfiles().Any());
            Assert.AreEqual(labResponse.User.Upn, account.Username);
            Assert.AreEqual("login.microsoftonline.us", account.Environment);

            Trace.WriteLine("Part 3 - Acquire a token silently");
            result = await pca
                     .AcquireTokenSilent(s_scopes, result.Account)
                     .ExecuteAsync(CancellationToken.None)
                     .ConfigureAwait(false);

            Assert.IsNotNull(result);
            Assert.IsNotNull(result.Account);
            Assert.IsNotNull(result.Account.GetTenantProfiles());
            Assert.IsTrue(result.Account.GetTenantProfiles().Any());
            Assert.IsTrue(labResponse.Lab.Authority.Contains(result.Account.Environment));
        }
        private async Task <AuthenticationResult> RunTestForUserAsync(LabResponse labResponse, string authority)
        {
            var cert = await s_secretProvider.GetCertificateWithPrivateMaterialAsync(
                CertificateName, KeyVaultInstance.MsalTeam).ConfigureAwait(false);

            IConfidentialClientApplication cca;
            string redirectUri = SeleniumWebUI.FindFreeLocalhostRedirectUri();

            cca = ConfidentialClientApplicationBuilder
                  .Create(ConfidentialClientID)
                  .WithAuthority(authority)
                  .WithCertificate(cert)
                  .WithRedirectUri(redirectUri)
                  .WithTestLogging()
                  .Build();

            Trace.WriteLine("Part 1 - Call GetAuthorizationRequestUrl to figure out where to go ");
            var startUri = await cca
                           .GetAuthorizationRequestUrl(s_scopes)
                           .ExecuteAsync()
                           .ConfigureAwait(false);

            Trace.WriteLine("Part 2 - Use a browser to login and to capture the authorization code ");
            var seleniumUi = new SeleniumWebUI((driver) =>
            {
                Trace.WriteLine("Starting Selenium automation");
                driver.PerformLogin(labResponse.User, Prompt.SelectAccount, false, false);
            }, TestContext);

            CancellationTokenSource cts = new CancellationTokenSource(s_timeout);
            Uri authCodeUri             = await seleniumUi.AcquireAuthorizationCodeAsync(
                startUri,
                new Uri(redirectUri),
                cts.Token)
                                          .ConfigureAwait(false);

            var authorizationResult = AuthorizationResult.FromUri(authCodeUri.AbsoluteUri);

            Assert.AreEqual(AuthorizationStatus.Success, authorizationResult.Status);

            Trace.WriteLine("Part 3 - Get a token using the auth code, just like a website");
            var result = await cca.AcquireTokenByAuthorizationCode(s_scopes, authorizationResult.Code)
                         .ExecuteAsync()
                         .ConfigureAwait(false);

            return(result);
        }
コード例 #8
0
        public async Task DefaultOsBrowser_IsCancellable_StartsCancelled_Async()
        {
            // Arrange
            var redirectUri = SeleniumWebUI.FindFreeLocalhostRedirectUri();
            var cts         = new CancellationTokenSource();
            IPublicClientApplication pca = InitWithCustomPlatformProxy(redirectUri);

            // Act Cancel token acquisition mediately
            cts.Cancel();

            var tokenTask = pca // do not wait for this to finish
                            .AcquireTokenInteractive(TestConstants.s_graphScopes)
                            .WithUseEmbeddedWebView(false)
                            .ExecuteAsync(cts.Token)
                            .ConfigureAwait(false);

            await ValidateOperationCancelledAsync(redirectUri, cts, tokenTask).ConfigureAwait(false);

            ValidatePortIsFree(new Uri(redirectUri).Port);
        }
コード例 #9
0
        public async Task FailingTest_SeleniumFailureAsync()
        {
            var pca = PublicClientApplicationBuilder
                      .Create("1d18b3b0-251b-4714-a02a-9956cec86c2d")
                      .WithRedirectUri(SeleniumWebUI.FindFreeLocalhostRedirectUri())
                      .Build();

            // This should fail after a few seconds
            var seleniumLogic = new SeleniumWebUI((driver) =>
            {
                Trace.WriteLine("Looking for an element that does not exist");
                driver.FindElement(By.Id("i_hope_this_element_does_not_exist"));
            }, TestContext);

            // The exception propagated to the test should be Selenium exception,
            // the test should not wait for the TCP listener to time out
            await AssertException.TaskThrowsAsync <NoSuchElementException>(() => pca
                                                                           .AcquireTokenInteractive(s_scopes)
                                                                           .WithCustomWebUi(seleniumLogic)
                                                                           .ExecuteAsync(CancellationToken.None))
            .ConfigureAwait(false);
        }
コード例 #10
0
        public async Task DefaultOsBrowser_IsCancellable_AfterAWhile_Async()
        {
            // Arrange
            var redirectUri = SeleniumWebUI.FindFreeLocalhostRedirectUri();
            var cts         = new CancellationTokenSource();
            IPublicClientApplication pca = InitWithCustomPlatformProxy(redirectUri);

            // Act - start with cancellation not requested
            var tokenTask = pca // do not wait for this to finish
                            .AcquireTokenInteractive(TestConstants.s_graphScopes)
                            .WithUseEmbeddedWebView(false)
                            .ExecuteAsync(cts.Token)
                            .ConfigureAwait(false);

            // Wait a bit to allow the webUI to start listening
            await Task.Delay(300).ConfigureAwait(false);

            // Cancel token acquisition while waiting for the browser to respond
            cts.Cancel();

            await ValidateOperationCancelledAsync(redirectUri, cts, tokenTask).ConfigureAwait(false);

            ValidatePortIsFree(new Uri(redirectUri).Port);
        }
コード例 #11
0
        private async Task <AuthenticationResult> RunTestForUserAsync(LabResponse labResponse, bool directToAdfs = false)
        {
            HttpSnifferClientFactory factory = null;
            IPublicClientApplication pca;

            if (directToAdfs)
            {
                pca = PublicClientApplicationBuilder
                      .Create(Adfs2019LabConstants.PublicClientId)
                      .WithRedirectUri(Adfs2019LabConstants.ClientRedirectUri)
                      .WithAdfsAuthority(Adfs2019LabConstants.Authority)
                      .WithTestLogging()
                      .Build();
            }
            else
            {
                pca = PublicClientApplicationBuilder
                      .Create(labResponse.App.AppId)
                      .WithRedirectUri(SeleniumWebUI.FindFreeLocalhostRedirectUri())
                      .WithAuthority(labResponse.Lab.Authority + "common")
                      .WithTestLogging(out factory)
                      .Build();
            }

            var userCacheAccess = pca.UserTokenCache.RecordAccess();

            Trace.WriteLine("Part 1 - Acquire a token interactively, no login hint");
            AuthenticationResult result = await pca
                                          .AcquireTokenInteractive(s_scopes)
                                          .WithCustomWebUi(CreateSeleniumCustomWebUI(labResponse.User, Prompt.SelectAccount, false, directToAdfs))
                                          .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token)
                                          .ConfigureAwait(false);

            Assert.IsTrue(result.AuthenticationResultMetadata.DurationTotalInMs > 0);
            Assert.IsTrue(result.AuthenticationResultMetadata.DurationInHttpInMs > 0);

            userCacheAccess.AssertAccessCounts(0, 1);
            IAccount account = await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false);

            userCacheAccess.AssertAccessCounts(1, 1); // the assert calls GetAccounts
            Assert.IsFalse(userCacheAccess.LastAfterAccessNotificationArgs.IsApplicationCache);

            Trace.WriteLine("Part 2 - Clear the cache");
            await pca.RemoveAsync(account).ConfigureAwait(false);

            userCacheAccess.AssertAccessCounts(1, 2);
            Assert.IsFalse((await pca.GetAccountsAsync().ConfigureAwait(false)).Any());
            userCacheAccess.AssertAccessCounts(2, 2);
            Assert.IsFalse(userCacheAccess.LastAfterAccessNotificationArgs.IsApplicationCache);

            if (factory?.RequestsAndResponses != null)
            {
                factory.RequestsAndResponses.Clear();
            }

            Trace.WriteLine("Part 3 - Acquire a token interactively again, with login hint");
            result = await pca
                     .AcquireTokenInteractive(s_scopes)
                     .WithCustomWebUi(CreateSeleniumCustomWebUI(labResponse.User, Prompt.ForceLogin, true, directToAdfs))
                     .WithPrompt(Prompt.ForceLogin)
                     .WithLoginHint(labResponse.User.Upn)
                     .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token)
                     .ConfigureAwait(false);

            userCacheAccess.AssertAccessCounts(2, 3);
            AssertCcsRoutingInformationIsSent(factory, labResponse);

            account = await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false);

            userCacheAccess.AssertAccessCounts(3, 3);
            Assert.IsFalse(userCacheAccess.LastAfterAccessNotificationArgs.IsApplicationCache);

            if (factory?.RequestsAndResponses != null)
            {
                factory.RequestsAndResponses.Clear();
            }

            Trace.WriteLine("Part 4 - Acquire a token silently");
            result = await pca
                     .AcquireTokenSilent(s_scopes, account)
                     .ExecuteAsync(CancellationToken.None)
                     .ConfigureAwait(false);

            Trace.WriteLine("Part 5 - Acquire a token silently with force refresh");
            result = await pca
                     .AcquireTokenSilent(s_scopes, account)
                     .WithForceRefresh(true)
                     .ExecuteAsync(CancellationToken.None)
                     .ConfigureAwait(false);

            await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false);

            Assert.IsFalse(userCacheAccess.LastAfterAccessNotificationArgs.IsApplicationCache);
            AssertCcsRoutingInformationIsSent(factory, labResponse);

            return(result);
        }
        private async Task RunTestForUserAsync(LabResponse labResponse, string authority, bool usePkce = false)
        {
            var cert = await s_secretProvider.GetCertificateWithPrivateMaterialAsync(
                CertificateName, KeyVaultInstance.MsalTeam).ConfigureAwait(false);

            IConfidentialClientApplication cca;
            string redirectUri = SeleniumWebUI.FindFreeLocalhostRedirectUri();

            HttpSnifferClientFactory factory;

            cca = ConfidentialClientApplicationBuilder
                  .Create(ConfidentialClientID)
                  .WithAuthority(authority)
                  .WithCertificate(cert)
                  .WithRedirectUri(redirectUri)
                  .WithTestLogging(out factory)
                  .Build();

            var cacheAccess = (cca as ConfidentialClientApplication).UserTokenCache.RecordAccess();

            Trace.WriteLine("Part 1 - Call GetAuthorizationRequestUrl to figure out where to go ");
            var authUriBuilder = cca
                                 .GetAuthorizationRequestUrl(s_scopes);

            string codeVerifier = "";

            if (usePkce)
            {
                authUriBuilder.WithPkce(out codeVerifier);
            }

            Uri authUri = await authUriBuilder.ExecuteAsync()
                          .ConfigureAwait(false);

            cacheAccess.AssertAccessCounts(0, 0);

            Trace.WriteLine("Part 2 - Use a browser to login and to capture the authorization code ");
            var seleniumUi = new SeleniumWebUI((driver) =>
            {
                Trace.WriteLine("Starting Selenium automation");
                driver.PerformLogin(labResponse.User, Prompt.SelectAccount, false, false);
            }, TestContext);

            CancellationTokenSource cts = new CancellationTokenSource(s_timeout);
            Uri authCodeUri             = await seleniumUi.AcquireAuthorizationCodeAsync(
                authUri,
                new Uri(redirectUri),
                cts.Token)
                                          .ConfigureAwait(false);

            var authorizationResult = AuthorizationResult.FromUri(authCodeUri.AbsoluteUri);

            Assert.AreEqual(AuthorizationStatus.Success, authorizationResult.Status);

            factory.RequestsAndResponses.Clear();

            Trace.WriteLine("Part 3 - Get a token using the auth code, just like a website");
            var result = await cca.AcquireTokenByAuthorizationCode(s_scopes, authorizationResult.Code)
                         .WithPkceCodeVerifier(codeVerifier)
                         .WithExtraHttpHeaders(TestConstants.ExtraHttpHeader)
                         .ExecuteAsync()
                         .ConfigureAwait(false);

            cacheAccess.AssertAccessCounts(0, 1);
            AssertCacheKey(cacheAccess, result.Account.HomeAccountId.Identifier);

            AssertExtraHTTPHeadersAreSent(factory);

            Trace.WriteLine("Part 4 - Remove Account");

            await cca.RemoveAsync(result.Account).ConfigureAwait(false);

            cacheAccess.AssertAccessCounts(0, 2);

            AssertCacheKey(cacheAccess, result.Account.HomeAccountId.Identifier);
        }