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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }