public async Task PKeyAuthNonInteractiveTestAsync() { //Arrange var labResponse = await LabUserHelper.GetSpecificUserAsync(_deviceAuthuser).ConfigureAwait(false); var factory = new HttpSnifferClientFactory(); var msalPublicClient = PublicClientApplicationBuilder .Create(labResponse.App.AppId) .WithAuthority("https://login.microsoftonline.com/organizations/") .WithHttpClientFactory(factory) .Build(); //Act var authResult = msalPublicClient.AcquireTokenByUsernamePassword( new[] { "user.read" }, labResponse.User.Upn, new NetworkCredential("", labResponse.User.GetOrFetchPassword()).SecurePassword) .WithClaims(JObject.Parse(_claims).ToString()) .ExecuteAsync(CancellationToken.None).Result; //Assert Assert.IsNotNull(authResult); Assert.IsNotNull(authResult.AccessToken); Assert.IsNotNull(authResult.IdToken); Assert.IsTrue(string.Equals(_deviceAuthuser, authResult.Account.Username, StringComparison.InvariantCultureIgnoreCase)); var(req, res) = factory.RequestsAndResponses .Where(x => x.Item1.RequestUri.AbsoluteUri == labResponse.Lab.Authority + "organizations/oauth2/v2.0/token" && x.Item2.StatusCode == HttpStatusCode.OK).ElementAt(1); var AuthHeader = req.Headers.Single(h => h.Key == "Authorization").Value.FirstOrDefault(); Assert.IsTrue(!string.IsNullOrEmpty(AuthHeader)); Assert.IsTrue(AuthHeader.Contains("PKeyAuth")); }
public async Task PKeyAuthNonInteractiveTestAsync() { //Arrange var labResponse = await LabUserHelper.GetSpecificUserAsync(_deviceAuthuser).ConfigureAwait(false); var factory = new HttpSnifferClientFactory(); var msalPublicClient = PublicClientApplicationBuilder .Create(labResponse.App.AppId) .WithAuthority("https://login.microsoftonline.com/organizations/") .WithHttpClientFactory(factory) .Build(); //Act var authResult = msalPublicClient.AcquireTokenByUsernamePassword( new[] { "user.read" }, labResponse.User.Upn, new NetworkCredential("", labResponse.User.GetOrFetchPassword()).SecurePassword) .WithClaims(JObject.Parse(_claims).ToString()) .ExecuteAsync(CancellationToken.None).Result; //Assert Assert.IsNotNull(authResult); Assert.IsNotNull(authResult.AccessToken); Assert.IsNotNull(authResult.IdToken); Assert.IsTrue(string.Equals(_deviceAuthuser, authResult.Account.Username, StringComparison.InvariantCultureIgnoreCase)); //Assert that the PKeyAuth header is used and the token response is successful var(req, res) = factory.RequestsAndResponses .Where(x => x.Item1.Headers.Authorization != null && x.Item1.Headers.Authorization.Scheme.Contains(PKeyAuthConstants.PKeyAuthName) && x.Item2.StatusCode == HttpStatusCode.OK).FirstOrDefault(); Assert.IsNotNull(req); Assert.IsNotNull(res); }
public async Task AcquireTokenByObo_LongRunning_WithDifferentScopes_TestAsync() { string[] scopes2 = { "api://eec635da-5760-452d-940a-448220db047c/access_as_user" }; var user1 = (await LabUserHelper.GetSpecificUserAsync("*****@*****.**").ConfigureAwait(false)).User; var pca = PublicClientApplicationBuilder .Create(PublicClientID) .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs) .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient") .Build(); var userAuthResult = await pca .AcquireTokenByUsernamePassword(s_oboServiceScope, user1.Upn, new NetworkCredential("", user1.GetOrFetchPassword()).SecurePassword) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); var cca = BuildCCA(userAuthResult.TenantId); string oboCacheKey = "obo-cache-key"; UserAssertion userAssertion = new UserAssertion(userAuthResult.AccessToken); var result = await cca.InitiateLongRunningProcessInWebApi(s_scopes, userAuthResult.AccessToken, ref oboCacheKey) .ExecuteAsync().ConfigureAwait(false); // Cache has 1 partition (user-provided key) with 1 token Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count); Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count); // No matching AT, uses RT to retrieve new AT. result = await cca.AcquireTokenInLongRunningProcess(scopes2, oboCacheKey).ExecuteAsync().ConfigureAwait(false); Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); Assert.AreEqual(CacheRefreshReason.NoCachedAccessToken, result.AuthenticationResultMetadata.CacheRefreshReason); }
public async Task AcquireTokenByObo_NormalOboThenLongRunningInitiate_WithTheSameKey_TestAsync() { var user1 = (await LabUserHelper.GetSpecificUserAsync("*****@*****.**").ConfigureAwait(false)).User; var pca = PublicClientApplicationBuilder .Create(PublicClientID) .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs) .Build(); var userAuthResult = await pca .AcquireTokenByUsernamePassword(s_oboServiceScope, user1.Upn, new NetworkCredential("", user1.GetOrFetchPassword()).SecurePassword) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); var cca = BuildCCA(userAuthResult.TenantId); UserAssertion userAssertion = new UserAssertion(userAuthResult.AccessToken); string oboCacheKey = userAssertion.AssertionHash; // AcquireNormal - AT from IdP via OBO flow(only new AT cached, no RT in cache) var result = await cca.AcquireTokenOnBehalfOf(s_scopes, userAssertion).ExecuteAsync().ConfigureAwait(false); Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count); Assert.AreEqual(0, cca.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count); // InitiateLR - AT from cache result = await cca.InitiateLongRunningProcessInWebApi(s_scopes, userAuthResult.AccessToken, ref oboCacheKey) .ExecuteAsync().ConfigureAwait(false); Assert.AreEqual(TokenSource.Cache, result.AuthenticationResultMetadata.TokenSource); // Expire AT TokenCacheHelper.ExpireAllAccessTokens(cca.UserTokenCacheInternal); // InitiateLR - AT via OBO flow (new AT, RT cached) result = await cca.InitiateLongRunningProcessInWebApi(s_scopes, userAuthResult.AccessToken, ref oboCacheKey) .ExecuteAsync().ConfigureAwait(false); Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count); Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count); // Expire AT TokenCacheHelper.ExpireAllAccessTokens(cca.UserTokenCacheInternal); // AcquireLR - AT from IdP via RT flow(new AT, RT cached) result = await cca.AcquireTokenInLongRunningProcess(s_scopes, oboCacheKey).ExecuteAsync().ConfigureAwait(false); Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count); Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count); }
public async Task OboAndClient_WithRegional_TestAsync() { // Setup: Get lab user, create PCA and get user tokens var user = (await LabUserHelper.GetSpecificUserAsync("*****@*****.**").ConfigureAwait(false)).User; var pca = PublicClientApplicationBuilder .Create(PublicClientID) .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs) .Build(); var userResult = await pca .AcquireTokenByUsernamePassword(s_oboServiceScope, user.Upn, new NetworkCredential("", user.GetOrFetchPassword()).SecurePassword) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); // Act and Assert different scenarios var cca = BuildCCA(userResult.TenantId, true); // OBO uses global - IdP var oboResult = await cca.AcquireTokenOnBehalfOf(s_scopes, new UserAssertion(userResult.AccessToken)) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreEqual(TokenSource.IdentityProvider, oboResult.AuthenticationResultMetadata.TokenSource); Assert.IsFalse(oboResult.AuthenticationResultMetadata.TokenEndpoint.Contains(TestConstants.Region)); // Client uses regional - IdP var clientResult = await cca.AcquireTokenForClient(new string[] { "https://graph.microsoft.com/.default" }) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreEqual(TokenSource.IdentityProvider, clientResult.AuthenticationResultMetadata.TokenSource); Assert.IsTrue(clientResult.AuthenticationResultMetadata.TokenEndpoint.Contains(TestConstants.Region)); // OBO from cache oboResult = await cca.AcquireTokenOnBehalfOf(s_scopes, new UserAssertion(userResult.AccessToken)) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreEqual(TokenSource.Cache, oboResult.AuthenticationResultMetadata.TokenSource); // Client from cache clientResult = await cca.AcquireTokenForClient(new string[] { "https://graph.microsoft.com/.default" }) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreEqual(TokenSource.Cache, clientResult.AuthenticationResultMetadata.TokenSource); }
public async Task AcquireTokenByObo_LongRunningAndNormalObo_WithDifferentKeys_TestAsync() { var user1 = (await LabUserHelper.GetSpecificUserAsync("*****@*****.**").ConfigureAwait(false)).User; var pca = PublicClientApplicationBuilder .Create(PublicClientID) .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs) .Build(); var userAuthResult = await pca .AcquireTokenByUsernamePassword(s_oboServiceScope, user1.Upn, new NetworkCredential("", user1.GetOrFetchPassword()).SecurePassword) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); var cca = BuildCCA(userAuthResult.TenantId); string oboCacheKey = "obo-cache-key"; UserAssertion userAssertion = new UserAssertion(userAuthResult.AccessToken); var result = await cca.InitiateLongRunningProcessInWebApi(s_scopes, userAuthResult.AccessToken, ref oboCacheKey) .ExecuteAsync().ConfigureAwait(false); // Cache has 1 partition (user-provided key) with 1 token Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count); Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count); result = await cca.AcquireTokenOnBehalfOf(s_scopes, userAssertion).ExecuteAsync().ConfigureAwait(false); // Cache has 2 partitions (user-provided key, assertion) with 1 token each Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); Assert.AreEqual(2, cca.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count); Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count); // Returns long-running token result = await cca.AcquireTokenInLongRunningProcess(s_scopes, oboCacheKey).ExecuteAsync().ConfigureAwait(false); Assert.AreEqual(TokenSource.Cache, result.AuthenticationResultMetadata.TokenSource); // Returns normal token result = await cca.AcquireTokenOnBehalfOf(s_scopes, userAssertion).ExecuteAsync().ConfigureAwait(false); Assert.AreEqual(TokenSource.Cache, result.AuthenticationResultMetadata.TokenSource); }
private static async Task<AuthenticationResult> AcquireTokenForLabUserAsync() { var labResponse = await LabUserHelper.GetSpecificUserAsync(TestConstants.OBOUser).ConfigureAwait(false); var msalPublicClient = PublicClientApplicationBuilder .Create(TestConstants.OBOClientSideClientId) .WithAuthority(labResponse.Lab.Authority, TestConstants.Organizations) .Build(); AuthenticationResult authResult = await msalPublicClient .AcquireTokenByUsernamePassword( TestConstants.OBOApiScope, TestConstants.OBOUser, new NetworkCredential( TestConstants.OBOUser, labResponse.User.GetOrFetchPassword()).SecurePassword) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); return authResult; }
public async Task WebAPIAccessingGraphOnBehalfOfUserTestAsync() { await RunOnBehalfOfTestAsync(await LabUserHelper.GetSpecificUserAsync("*****@*****.**").ConfigureAwait(false)).ConfigureAwait(false); }
public async Task OboAndSilent_Async(bool serializeCache, bool usePartitionedSerializationCache) { // Setup: Get lab users, create PCA and get user tokens var user1 = (await LabUserHelper.GetSpecificUserAsync("*****@*****.**").ConfigureAwait(false)).User; var user2 = (await LabUserHelper.GetSpecificUserAsync("*****@*****.**").ConfigureAwait(false)).User; var partitionedInMemoryTokenCache = new InMemoryPartitionedTokenCache(); var nonPartitionedInMemoryTokenCache = new InMemoryTokenCache(); var oboTokens = new HashSet <string>(); var pca = PublicClientApplicationBuilder .Create(PublicClientID) .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs) .Build(); var user1AuthResult = await pca .AcquireTokenByUsernamePassword(s_oboServiceScope, user1.Upn, new NetworkCredential("", user1.GetOrFetchPassword()).SecurePassword) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); var user2AuthResult = await pca .AcquireTokenByUsernamePassword(s_oboServiceScope, user2.Upn, new NetworkCredential("", user2.GetOrFetchPassword()).SecurePassword) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreEqual(user1AuthResult.TenantId, user2AuthResult.TenantId); var cca = CreateCCA(); // Asserts // Silent calls should throw await AssertException.TaskThrowsAsync <MsalUiRequiredException>(() => cca.AcquireTokenSilent(s_scopes, user1.Upn) .ExecuteAsync(CancellationToken.None) ).ConfigureAwait(false); await AssertException.TaskThrowsAsync <MsalUiRequiredException>(() => cca.AcquireTokenSilent(s_scopes, user2.Upn) .ExecuteAsync(CancellationToken.None) ).ConfigureAwait(false); // User1 - no AT, RT in cache - retrieves from IdP var authResult = await cca.AcquireTokenOnBehalfOf(s_scopes, new UserAssertion(user1AuthResult.AccessToken)) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreEqual(TokenSource.IdentityProvider, authResult.AuthenticationResultMetadata.TokenSource); Assert.AreEqual(CacheRefreshReason.NoCachedAccessToken, authResult.AuthenticationResultMetadata.CacheRefreshReason); oboTokens.Add(authResult.AccessToken); // User1 - finds AT in cache authResult = await cca.AcquireTokenOnBehalfOf(s_scopes, new UserAssertion(user1AuthResult.AccessToken)) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreEqual(TokenSource.Cache, authResult.AuthenticationResultMetadata.TokenSource); Assert.AreEqual(CacheRefreshReason.NotApplicable, authResult.AuthenticationResultMetadata.CacheRefreshReason); oboTokens.Add(authResult.AccessToken); // User2 - no AT, RT - retrieves from IdP authResult = await cca.AcquireTokenOnBehalfOf(s_scopes, new UserAssertion(user2AuthResult.AccessToken)) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreEqual(TokenSource.IdentityProvider, authResult.AuthenticationResultMetadata.TokenSource); Assert.AreEqual(CacheRefreshReason.NoCachedAccessToken, authResult.AuthenticationResultMetadata.CacheRefreshReason); oboTokens.Add(authResult.AccessToken); // User2 - finds AT in cache authResult = await cca.AcquireTokenOnBehalfOf(s_scopes, new UserAssertion(user2AuthResult.AccessToken)) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreEqual(TokenSource.Cache, authResult.AuthenticationResultMetadata.TokenSource); Assert.AreEqual(CacheRefreshReason.NotApplicable, authResult.AuthenticationResultMetadata.CacheRefreshReason); oboTokens.Add(authResult.AccessToken); Assert.AreEqual(2, oboTokens.Count); // Silent calls should throw await AssertException.TaskThrowsAsync <MsalUiRequiredException>(() => cca.AcquireTokenSilent(s_scopes, user1.Upn) .ExecuteAsync(CancellationToken.None) ).ConfigureAwait(false); await AssertException.TaskThrowsAsync <MsalUiRequiredException>(() => cca.AcquireTokenSilent(s_scopes, user2.Upn) .ExecuteAsync(CancellationToken.None) ).ConfigureAwait(false); IConfidentialClientApplication CreateCCA() { var app = ConfidentialClientApplicationBuilder .Create(OboConfidentialClientID) .WithAuthority(new Uri($"https://login.microsoftonline.com/{user1AuthResult.TenantId}"), true) .WithClientSecret(_confidentialClientSecret) .WithLegacyCacheCompatibility(false) .Build(); if (serializeCache) { if (usePartitionedSerializationCache) { partitionedInMemoryTokenCache.Bind(app.UserTokenCache); } else { nonPartitionedInMemoryTokenCache.Bind(app.UserTokenCache); } } return(app); } }