public async Task AcquireTokenSilent_LoginHint_MultipleAccountsAsync() { var receiver = new MyReceiver(); using (var httpManager = new MockHttpManager()) { PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithAuthority(new Uri(TestConstants.AuthorityTestTenant), true) .WithHttpManager(httpManager) .WithTelemetry(receiver.HandleTelemetryEvents) .BuildConcrete(); var tokenCacheHelper = new TokenCacheHelper(); var cacheAccess = app.UserTokenCache.RecordAccess(); tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor, "uid1", "utid"); tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor, "uid2", "utid"); var exception = await AssertException.TaskThrowsAsync <MsalUiRequiredException>(async() => await app.AcquireTokenSilent( TestConstants.s_scope.ToArray(), TestConstants.DisplayableId) .WithAuthority(app.Authority, false) .ExecuteAsync().ConfigureAwait(false)).ConfigureAwait(false); Assert.AreEqual(MsalError.MultipleAccountsForLoginHint, exception.ErrorCode); Assert.AreEqual(UiRequiredExceptionClassification.AcquireTokenSilentFailed, exception.Classification); cacheAccess.AssertAccessCounts(1, 0); } }
public async Task TestAccountAcrossMultipleClientIdsAsync() { // Arrange var tokenCacheHelper = new TokenCacheHelper(); PublicClientApplication app = PublicClientApplicationBuilder .Create(TestConstants.ClientId) .WithTelemetry(new TraceTelemetryConfig()) .BuildConcrete(); // Populate with tokens tied to ClientId2 tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor, clientId: TestConstants.ClientId2); var cacheAccessRecorder = app.UserTokenCache.RecordAccess(); app.UserTokenCacheInternal.Accessor.AssertItemCount( expectedAtCount: 2, expectedRtCount: 1, expectedAccountCount: 1, expectedIdtCount: 1, expectedAppMetadataCount: 1); // Act var accounts = await app.GetAccountsAsync().ConfigureAwait(false); // Assert Assert.IsFalse(accounts.Any(), "No accounts should be returned because the existing account to a different client"); cacheAccessRecorder.AssertAccessCounts(1, 0); // Arrange // Populate for clientid2 tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor, clientId: TestConstants.ClientId); app.UserTokenCacheInternal.Accessor.AssertItemCount( expectedAtCount: 4, expectedRtCount: 2, expectedAccountCount: 1, // still 1 account expectedIdtCount: 2, expectedAppMetadataCount: 2); // Act accounts = await app.GetAccountsAsync().ConfigureAwait(false); cacheAccessRecorder.AssertAccessCounts(2, 0); Assert.IsTrue(cacheAccessRecorder.LastAfterAccessNotificationArgs.HasTokens); await app.RemoveAsync(accounts.Single()).ConfigureAwait(false); // Assert cacheAccessRecorder.AssertAccessCounts(2, 1); app.UserTokenCacheInternal.Accessor.AssertItemCount( expectedAtCount: 2, expectedRtCount: 1, expectedAccountCount: 0, expectedIdtCount: 1, expectedAppMetadataCount: 2); // app metadata is never deleted }
public async Task ExpiredTokenRefreshFlowTestAsync() { using (var harness = new MockHttpTestHarness(TestConstants.AuthorityHomeTenant)) { _tokenCacheHelper.PopulateCache(harness.Cache.Accessor); var parameters = harness.CreateRequestParams( harness.Cache, null, TestConstants.ExtraQueryParameters, TestConstants.Claims, authorityOverride: AuthorityInfo.FromAuthorityUri(TestConstants.AuthorityHomeTenant, false)); var silentParameters = new AcquireTokenSilentParameters() { Account = new Account(TestConstants.HomeAccountId, TestConstants.DisplayableId, TestConstants.ProductionPrefCacheEnvironment), }; // set access tokens as expired foreach (var accessItem in (await harness.Cache.GetAllAccessTokensAsync(true).ConfigureAwait(false))) { accessItem.ExpiresOnUnixTimestamp = ((long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds) .ToString(CultureInfo.InvariantCulture); harness.Cache.AddAccessTokenCacheItem(accessItem); } harness.HttpManager.AddInstanceDiscoveryMockHandler(); harness.HttpManager.AddMockHandler( new MockHttpMessageHandler() { ExpectedMethod = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage(), ExpectedQueryParams = TestConstants.ExtraQueryParameters, ExpectedPostData = new Dictionary <string, string>() { { OAuth2Parameter.Claims, TestConstants.Claims } } }); var request = new SilentRequest(harness.ServiceBundle, parameters, silentParameters); Task <AuthenticationResult> task = request.RunAsync(CancellationToken.None); var result = task.Result; Assert.IsNotNull(result); Assert.AreEqual("some-access-token", result.AccessToken); Assert.AreEqual(TestConstants.s_scope.AsSingleString(), result.Scopes.AsSingleString()); } }
private static ConfidentialClientApplication SetupCca(MockHttpAndServiceBundle harness) { ConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(TestConstants.ClientId) .WithAuthority(AzureCloudInstance.AzurePublic, TestConstants.Utid) .WithClientSecret(TestConstants.ClientSecret) .WithHttpManager(harness.HttpManager) .BuildConcrete(); var tokenCacheHelper = new TokenCacheHelper(); tokenCacheHelper.PopulateCache(app.AppTokenCacheInternal.Accessor, addSecondAt: false); tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor, addSecondAt: false, userAssertion: TestConstants.UserAssertion); return(app); }
public void FindAccessToken_ScopeCaseInsensitive() { var tokenCache = new TokenCache() { ClientId = TestConstants.ClientId }; TokenCacheHelper.PopulateCache(tokenCache.TokenCacheAccessor); var param = new AuthenticationRequestParameters() { RequestContext = new RequestContext(Guid.Empty, null), ClientId = TestConstants.ClientId, Authority = Authority.CreateAuthority(TestConstants.AuthorityHomeTenant, false), Scope = new SortedSet <string>(), User = TestConstants.User }; var scopeInCache = TestConstants.Scope.FirstOrDefault(); var upperCaseScope = scopeInCache.ToUpper(); param.Scope.Add(upperCaseScope); var item = tokenCache.FindAccessToken(param); Assert.IsNotNull(item); Assert.IsTrue(item.ScopeSet.Contains(scopeInCache)); }
public void AcquireTokenSilentScopeAndUserOverloadWithNoMatchingScopesInCacheTest() { // this test ensures that the API can // get authority (if unique) from the cache entries where scope does not match. // it should only happen for case where no authority is passed. using (var httpManager = new MockHttpManager()) { PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithAuthority(new Uri(ClientApplicationBase.DefaultAuthority), true) .WithHttpManager(httpManager) .BuildConcrete(); TokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor); var cacheAccess = app.UserTokenCache.RecordAccess(); Task <AuthenticationResult> task = app .AcquireTokenSilent( TestConstants.s_scopeForAnotherResource.ToArray(), new Account(TestConstants.s_userIdentifier, TestConstants.DisplayableId, null)) .ExecuteAsync(CancellationToken.None); AuthenticationResult result = task.Result; Assert.IsNotNull(result); Assert.AreEqual(TestConstants.DisplayableId, result.Account.Username); Assert.AreEqual(TestConstants.s_scopeForAnotherResource.AsSingleString(), result.Scopes.AsSingleString()); Assert.AreEqual(2, app.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); cacheAccess.AssertAccessCounts(1, 0); } }
public void AcquireTokenSilentScopeAndUserOverloadTenantSpecificAuthorityTest() { using (var httpManager = new MockHttpManager()) { PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithAuthority(new Uri(TestConstants.AuthorityGuestTenant), true) .WithHttpManager(httpManager) .BuildConcrete(); TokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor); httpManager.AddInstanceDiscoveryMockHandler(); httpManager.AddMockHandler( new MockHttpMessageHandler() { ExpectedMethod = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage( TestConstants.Uid, TestConstants.DisplayableId, TestConstants.s_scope.ToArray()) }); Task <AuthenticationResult> task = app .AcquireTokenSilent( TestConstants.s_scope.ToArray(), new Account(TestConstants.s_userIdentifier, TestConstants.DisplayableId, null)) .ExecuteAsync(CancellationToken.None); AuthenticationResult result = task.Result; Assert.IsNotNull(result); Assert.AreEqual(TestConstants.DisplayableId, result.Account.Username); Assert.AreEqual(TestConstants.s_scope.AsSingleString(), result.Scopes.AsSingleString()); } }
public async Task AcquireTokenSilent_LoginHintAsync() { using (var httpManager = new MockHttpManager()) { PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithAuthority(new Uri(TestConstants.AuthorityTestTenant), true) .WithHttpManager(httpManager) .WithTelemetry(new TraceTelemetryConfig()) .BuildConcrete(); var tokenCacheHelper = new TokenCacheHelper(); tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor); var cacheAccess = app.UserTokenCache.RecordAccess(); AuthenticationResult result = await app.AcquireTokenSilent( TestConstants.s_scope.ToArray(), TestConstants.DisplayableId) .WithAuthority(app.Authority, false) .ExecuteAsync() .ConfigureAwait(false); Assert.IsNotNull(result); Assert.AreEqual(TestConstants.DisplayableId, result.Account.Username); Assert.AreEqual(TestConstants.s_scope.AsSingleString(), result.Scopes.AsSingleString()); cacheAccess.AssertAccessCounts(1, 0); } }
public async Task AcquireTokenSilent_BypassesCacheForAccessTokens_IfClaimsUsed_Async() { using (var harness = CreateTestHarness()) { Trace.WriteLine("1. Setup an app with a token cache with a valid AT"); PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithHttpManager(harness.HttpManager) .BuildConcrete(); TokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor, addSecondAt: false); Trace.WriteLine("2. Silent Request without claims returns the AT from the cache"); var account = (await app.GetAccountsAsync().ConfigureAwait(false)).Single(); var result = await app.AcquireTokenSilent(TestConstants.s_scope, account) .ExecuteAsync() .ConfigureAwait(false); Assert.IsNotNull(result, "A result is obtained from the cache, i.e. without HTTP calls"); Trace.WriteLine("3. Silent Request + WithClaims does not return an AT from the cache"); harness.HttpManager.AddInstanceDiscoveryMockHandler(TestConstants.AuthorityUtidTenant); harness.HttpManager.AddSuccessTokenResponseMockHandlerForPost(TestConstants.AuthorityUtidTenant); result = await app.AcquireTokenSilent(TestConstants.s_scope, account) .WithClaims(TestConstants.Claims) .ExecuteAsync() .ConfigureAwait(false); Assert.IsNotNull(result, "An access token is no longer obtained from the cache. The RT is used to get one from the STS."); } }
public void AcquireTokenSilentScopeAndUserOverloadDefaultAuthorityTest() { using (var httpManager = new MockHttpManager()) { PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithAuthority(new Uri(TestConstants.AuthorityTestTenant), true) .WithHttpManager(httpManager) .WithTelemetry(new TraceTelemetryConfig()) .BuildConcrete(); var tokenCacheHelper = new TokenCacheHelper(); tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor); app.UserTokenCacheInternal.Accessor.DeleteAccessToken( new MsalAccessTokenCacheKey( TestConstants.ProductionPrefNetworkEnvironment, TestConstants.Utid, TestConstants.s_userIdentifier, TestConstants.ClientId, TestConstants.ScopeForAnotherResourceStr, TestConstants.Bearer)); Task <AuthenticationResult> task = app .AcquireTokenSilent( TestConstants.s_scope.ToArray(), new Account(TestConstants.s_userIdentifier, TestConstants.DisplayableId, null)) .ExecuteAsync(CancellationToken.None); AuthenticationResult result = task.Result; Assert.IsNotNull(result); Assert.AreEqual(TestConstants.DisplayableId, result.Account.Username); Assert.AreEqual(TestConstants.s_scope.AsSingleString(), result.Scopes.AsSingleString()); } }
public async Task AfterAccess_Is_Called_When_BeforeAceess_Throws_Async() { using (var harness = CreateTestHarness()) { var pca = PublicClientApplicationBuilder .Create(TestConstants.ClientId) .WithHttpManager(harness.HttpManager) .BuildConcrete(); TokenCacheHelper.PopulateCache(pca.UserTokenCacheInternal.Accessor, addSecondAt: false); var account = (await pca.GetAccountsAsync().ConfigureAwait(false)).First(); // All these actions trigger a reloading of the cache await RunAfterAccessFailureAsync(pca, () => pca.GetAccountsAsync()).ConfigureAwait(false); await RunAfterAccessFailureAsync(pca, () => pca.AcquireTokenSilent(new[] { "User.Read" }, account).ExecuteAsync()) .ConfigureAwait(false); await RunAfterAccessFailureAsync(pca, () => pca.RemoveAsync(account)).ConfigureAwait(false); // AcquireTokenInteractive will save a token to the cache, but needs more setup harness.HttpManager.AddInstanceDiscoveryMockHandler(); harness.HttpManager.AddSuccessTokenResponseMockHandlerForPost(TestConstants.AuthorityCommonTenant); pca.ServiceBundle.ConfigureMockWebUI(); await RunAfterAccessFailureAsync(pca, () => pca.AcquireTokenInteractive(new[] { "User.Read" }).ExecuteAsync()) .ConfigureAwait(false); } }
public void ForceRefreshParameterFalseTestAsync() { var cache = new TokenCache(); TokenCacheHelper.PopulateCache(cache.TokenCacheAccessor); var authority = Authority.CreateAuthority(TestConstants.AuthorityHomeTenant, false).CanonicalAuthority; var app = new ConfidentialClientApplication(TestConstants.ClientId, authority, TestConstants.RedirectUri, new ClientCredential(TestConstants.ClientSecret), null, cache) { ValidateAuthority = false }; var accessTokens = cache.GetAllAccessTokensForClient(new RequestContext(Guid.NewGuid(), null)); var accessTokenInCache = accessTokens.Where( item => item.ScopeSet.ScopeContains(TestConstants.Scope)) .ToList() .FirstOrDefault(); //add mock to fail in case of network call HttpMessageHandlerFactory.AddMockHandler(new MockHttpMessageHandler { ExceptionToThrow = new AssertFailedException("Unexpected Network Call") }); var task = app.AcquireTokenForClientAsync(TestConstants.Scope, false); var result = task.Result; Assert.AreEqual(accessTokenInCache?.AccessToken, result.AccessToken); }
public void AcquireTokenSilentScopeAndUserOverloadTenantSpecificAuthorityTest() { PublicClientApplication app = new PublicClientApplication(TestConstants.ClientId, TestConstants.AuthorityGuestTenant) { ValidateAuthority = false }; cache = new TokenCache() { ClientId = TestConstants.ClientId }; app.UserTokenCache = cache; TokenCacheHelper.PopulateCache(cache.TokenCacheAccessor); cache.TokenCacheAccessor.AccessTokenCacheDictionary.Remove(new AccessTokenCacheKey( TestConstants.AuthorityGuestTenant, TestConstants.ScopeForAnotherResource, TestConstants.ClientId, TestConstants.UserIdentifier).ToString()); Task <AuthenticationResult> task = app.AcquireTokenSilentAsync(TestConstants.Scope.ToArray(), new User() { DisplayableId = TestConstants.DisplayableId, Identifier = TestConstants.UserIdentifier, }); AuthenticationResult result = task.Result; Assert.IsNotNull(result); Assert.AreEqual(TestConstants.DisplayableId, result.User.DisplayableId); Assert.AreEqual(TestConstants.Scope.AsSingleString(), result.Scopes.AsSingleString()); }
public void AcquireTokenSilentCacheOnlyLookupTest() { PublicClientApplication app = new PublicClientApplication(TestConstants.ClientId, TestConstants.AuthorityHomeTenant) { ValidateAuthority = false }; cache = new TokenCache() { ClientId = TestConstants.ClientId }; app.UserTokenCache = cache; TokenCacheHelper.PopulateCache(cache.TokenCacheAccessor); cache.TokenCacheAccessor.AccessTokenCacheDictionary.Remove(new AccessTokenCacheKey( TestConstants.AuthorityGuestTenant, TestConstants.ScopeForAnotherResource, TestConstants.ClientId, TestConstants.UserIdentifier).ToString()); Task <AuthenticationResult> task = app.AcquireTokenSilentAsync(TestConstants.Scope.ToArray(), new User() { DisplayableId = TestConstants.DisplayableId, Identifier = TestConstants.UserIdentifier, }, app.Authority, false); AuthenticationResult result = task.Result; Assert.IsNotNull(result); Assert.AreEqual(TestConstants.DisplayableId, result.User.DisplayableId); Assert.AreEqual(TestConstants.Scope.AsSingleString(), result.Scopes.AsSingleString()); Assert.IsNotNull(_myReceiver.EventsReceived.Find(anEvent => // Expect finding such an event anEvent[EventBase.EventNameKey].EndsWith("api_event") && anEvent[ApiEvent.WasSuccessfulKey] == "true" && anEvent[ApiEvent.ApiIdKey] == "31")); }
public async Task AcquireTokenSilentScopeAndUserMultipleTokensFoundTest() { PublicClientApplication app = new PublicClientApplication(TestConstants.ClientId) { ValidateAuthority = false }; cache = new TokenCache() { ClientId = TestConstants.ClientId }; app.UserTokenCache = cache; TokenCacheHelper.PopulateCache(cache.TokenCacheAccessor); try { AuthenticationResult result = await app.AcquireTokenSilentAsync(TestConstants.Scope.ToArray(), new User() { DisplayableId = TestConstants.DisplayableId, Identifier = TestConstants.UserIdentifier, }) .ConfigureAwait(false); } catch (MsalClientException exc) { Assert.AreEqual(MsalClientException.MultipleTokensMatchedError, exc.ErrorCode); } }
public async Task TelemetryCacheRefreshTestAsync() { using (_harness = CreateTestHarness()) { _harness.HttpManager.AddInstanceDiscoveryMockHandler(); _app = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithHttpManager(_harness.HttpManager) .WithDefaultRedirectUri() .WithLogging((lvl, msg, pii) => Trace.WriteLine($"[MSAL_LOG][{lvl}] {msg}")) .BuildConcrete(); TokenCacheHelper.PopulateCache(_app.UserTokenCacheInternal.Accessor, addSecondAt: false); Trace.WriteLine("Step 1. Acquire Token Interactive successful"); var result = await RunAcquireTokenInteractiveAsync(AcquireTokenInteractiveOutcome.Success).ConfigureAwait(false); AssertCurrentTelemetry(result.HttpRequest, ApiIds.AcquireTokenInteractive, CacheRefreshReason.NotApplicable); AssertPreviousTelemetry(result.HttpRequest, expectedSilentCount: 0); Trace.WriteLine("Step 2. Acquire Token Silent successful - AT served from cache"); result = await RunAcquireTokenSilentAsync(AcquireTokenSilentOutcome.SuccessFromCache).ConfigureAwait(false); Assert.IsNull(result.HttpRequest, "No calls are made to the token endpoint"); Trace.WriteLine("Step 3. Acquire Token Silent successful - via expired token"); UpdateATWithRefreshOn(_app.UserTokenCacheInternal.Accessor, expired: true); TokenCacheAccessRecorder cacheAccess = _app.UserTokenCache.RecordAccess(); result = await RunAcquireTokenSilentAsync(AcquireTokenSilentOutcome.SuccessViaCacheRefresh).ConfigureAwait(false); AssertCurrentTelemetry(result.HttpRequest, ApiIds.AcquireTokenSilent, CacheRefreshReason.Expired, isCacheSerialized: true); AssertPreviousTelemetry(result.HttpRequest, expectedSilentCount: 1); Trace.WriteLine("Step 4. Acquire Token Silent successful - via refresh on"); UpdateATWithRefreshOn(_app.UserTokenCacheInternal.Accessor); cacheAccess = _app.UserTokenCache.RecordAccess(); result = await RunAcquireTokenSilentAsync(AcquireTokenSilentOutcome.SuccessViaCacheRefresh).ConfigureAwait(false); AssertCurrentTelemetry(result.HttpRequest, ApiIds.AcquireTokenSilent, CacheRefreshReason.ProactivelyRefreshed, isCacheSerialized: true); // Use reflection to get the value and wait till achieved HttpTelemetryManager httpTelemetryManager = (HttpTelemetryManager)_app.ServiceBundle.HttpTelemetryManager; Type httpTeleMgrType = typeof(HttpTelemetryManager); FieldInfo field = httpTeleMgrType.GetField("_successfullSilentCallCount", BindingFlags.NonPublic | BindingFlags.Instance); Assert.IsTrue(YieldTillSatisfied(() => { var actual = (int)field.GetValue(httpTelemetryManager); return(actual == 0); })); Trace.WriteLine("Step 5. Acquire Token Silent with force_refresh = true"); result = await RunAcquireTokenSilentAsync(AcquireTokenSilentOutcome.SuccessViaCacheRefresh, forceRefresh : true).ConfigureAwait(false); AssertCurrentTelemetry(result.HttpRequest, ApiIds.AcquireTokenSilent, CacheRefreshReason.ForceRefreshOrClaims, isCacheSerialized: true); Assert.IsTrue(YieldTillSatisfied(() => { var actual = (int)field.GetValue(httpTelemetryManager); return(actual == 0); })); } }
[TestCategory(TestCategories.Regression)] //https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/2706 public async Task NullAndIosBroker_RemoveAccounts_Async(Type brokerType) { using (var harness = CreateTestHarness()) { var broker = CreateBroker(brokerType); var builder = PublicClientApplicationBuilder .Create(TestConstants.ClientId) .WithHttpManager(harness.HttpManager); builder.Config.BrokerCreatorFunc = (parent, config, logger) => { return(broker); }; var app = builder.WithBroker(true).BuildConcrete(); TokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor); // Act var accounts = await app.GetAccountsAsync().ConfigureAwait(false); await app.RemoveAsync(accounts.Single()).ConfigureAwait(false); var accounts2 = await app.GetAccountsAsync().ConfigureAwait(false); // Assert Assert.AreEqual(1, accounts.Count()); Assert.IsFalse(accounts2.Any()); } }
public async Task BrokerSilentRequestTestExecutorAsync(bool brokerConfiguredByUser, bool brokerIsInstalledAndInvokable) { string brokerID = "*****@*****.**"; using (var harness = new MockHttpTestHarness(TestConstants.AuthorityHomeTenant)) { // resul will be from the cache TokenCacheHelper.PopulateCache(harness.Cache.Accessor, TestConstants.Uid, TestConstants.Utid, TestConstants.ClientId, TestConstants.ProductionPrefCacheEnvironment, brokerID); IBroker mockBroker = Substitute.For <IBroker>(); mockBroker.IsBrokerInstalledAndInvokable().ReturnsForAnyArgs(brokerIsInstalledAndInvokable); harness.ServiceBundle.Config.BrokerCreatorFunc = (app, config, logger) => mockBroker; var parameters = harness.CreateRequestParams( harness.Cache, null, TestConstants.ExtraQueryParameters, null, authorityOverride: AuthorityInfo.FromAuthorityUri(TestConstants.AuthorityCommonTenant, false)); parameters.AppConfig.IsBrokerEnabled = brokerConfiguredByUser; var silentParameters = new AcquireTokenSilentParameters() { Account = new Account(TestConstants.HomeAccountId, TestConstants.DisplayableId, TestConstants.ProductionPrefCacheEnvironment), }; var request = new SilentRequest(harness.ServiceBundle, parameters, silentParameters); var result = await request.RunAsync(default).ConfigureAwait(false);
public async Task SuggestedCacheKeyTestAsync() { // Arrange using (var httpManager = new MockHttpManager()) { PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithAuthority(new Uri(ClientApplicationBase.DefaultAuthority), true) .WithHttpManager(httpManager) .WithTelemetry(new TraceTelemetryConfig()) .BuildConcrete(); var tokenCacheHelper = new TokenCacheHelper(); tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor); var cacheAccess = app.UserTokenCache.RecordAccess(); // Act var allAccounts = await app.GetAccountsAsync().ConfigureAwait(false); // Assert Assert.IsNull(cacheAccess.LastAfterAccessNotificationArgs.SuggestedCacheKey, "Cannot suggest a key for GetAccounts"); Assert.AreEqual(1, allAccounts.Count()); cacheAccess.AssertAccessCounts(1, 0); // Act string homeAccId = allAccounts.Single().HomeAccountId.Identifier; IAccount accountById = await app.GetAccountAsync(homeAccId).ConfigureAwait(false); Assert.IsNotNull(accountById); cacheAccess.AssertAccessCounts(2, 0); // Assert Assert.AreEqual(homeAccId, cacheAccess.LastAfterAccessNotificationArgs.SuggestedCacheKey); Assert.AreEqual(homeAccId, cacheAccess.LastBeforeAccessNotificationArgs.SuggestedCacheKey); Assert.AreEqual(homeAccId, accountById.HomeAccountId.Identifier); // Act await app.AcquireTokenSilent(TestConstants.s_scope, accountById).ExecuteAsync().ConfigureAwait(false); // Assert cacheAccess.AssertAccessCounts(3, 0); Assert.AreEqual(homeAccId, cacheAccess.LastAfterAccessNotificationArgs.SuggestedCacheKey); Assert.AreEqual(homeAccId, cacheAccess.LastBeforeAccessNotificationArgs.SuggestedCacheKey); // Act await app.AcquireTokenSilent(TestConstants.s_scope, accountById.Username).ExecuteAsync().ConfigureAwait(false); // Assert cacheAccess.AssertAccessCounts(4, 0); Assert.IsNull(cacheAccess.LastAfterAccessNotificationArgs.SuggestedCacheKey, "MSAL does not know the home account id of the account associated with this username. It needs to load the cache first."); // Act await app.RemoveAsync(accountById).ConfigureAwait(false); cacheAccess.AssertAccessCounts(4, 1); Assert.AreEqual(homeAccId, cacheAccess.LastAfterAccessNotificationArgs.SuggestedCacheKey); Assert.AreEqual(homeAccId, cacheAccess.LastBeforeAccessNotificationArgs.SuggestedCacheKey); } }
public void ExpiredTokenRefreshFlowTest() { using (var httpManager = new MockHttpManager()) { var serviceBundle = ServiceBundle.CreateWithCustomHttpManager(httpManager); var aadInstanceDiscovery = new AadInstanceDiscovery(httpManager, new TelemetryManager()); Authority authority = Authority.CreateAuthority(serviceBundle, MsalTestConstants.AuthorityHomeTenant, false); TokenCache cache = new TokenCache() { ClientId = MsalTestConstants.ClientId, ServiceBundle = serviceBundle }; _tokenCacheHelper.PopulateCache(cache.TokenCacheAccessor); AuthenticationRequestParameters parameters = new AuthenticationRequestParameters() { Authority = authority, ClientId = MsalTestConstants.ClientId, Scope = MsalTestConstants.Scope, TokenCache = cache, RequestContext = new RequestContext(null, new MsalLogger(Guid.Empty, null)), Account = new Account(MsalTestConstants.UserIdentifier, MsalTestConstants.DisplayableId, null) }; // set access tokens as expired foreach (var atCacheItemStr in cache.GetAllAccessTokenCacheItems(new RequestContext(null, new MsalLogger(Guid.NewGuid(), null)))) { MsalAccessTokenCacheItem accessItem = JsonHelper.DeserializeFromJson <MsalAccessTokenCacheItem>(atCacheItemStr); accessItem.ExpiresOnUnixTimestamp = ((long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds).ToString(CultureInfo.InvariantCulture); cache.AddAccessTokenCacheItem(accessItem); } TestCommon.MockInstanceDiscoveryAndOpenIdRequest(httpManager); httpManager.AddMockHandler(new MockHttpMessageHandler() { Method = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage() }); var crypto = PlatformProxyFactory.GetPlatformProxy().CryptographyManager; SilentRequest request = new SilentRequest( serviceBundle, parameters, ApiEvent.ApiIds.None, false); Task <AuthenticationResult> task = request.RunAsync(CancellationToken.None); AuthenticationResult result = task.Result; Assert.IsNotNull(result); Assert.AreEqual("some-access-token", result.AccessToken); Assert.AreEqual(MsalTestConstants.Scope.AsSingleString(), result.Scopes.AsSingleString()); } }
private void RunAcquireTokenSilentCacheOnlyTest(string authority, bool expectNetworkDiscovery) { var receiver = new MyReceiver(); using (MockHttpAndServiceBundle testHarness = base.CreateTestHarness()) { PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithAuthority(authority, true) .WithHttpManager(testHarness.HttpManager) .WithTelemetry(receiver.HandleTelemetryEvents) .BuildConcrete(); var tokenCacheHelper = new TokenCacheHelper(); tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor); app.UserTokenCacheInternal.Accessor.DeleteAccessToken(new MsalAccessTokenCacheKey( TestConstants.ProductionPrefNetworkEnvironment, TestConstants.Utid, TestConstants.s_userIdentifier, TestConstants.ClientId, TestConstants.ScopeForAnotherResourceStr, TestConstants.Bearer)); if (expectNetworkDiscovery) { string host = new Uri(authority).Host; string discoveryHost = KnownMetadataProvider.IsKnownEnvironment(host) ? host : AadAuthority.DefaultTrustedHost; string discoveryEndpoint = $"https://{discoveryHost}/common/discovery/instance"; var jsonResponse = TestConstants.DiscoveryJsonResponse.Replace("login.microsoft.com", host); testHarness.HttpManager.AddMockHandler( MockHelpers.CreateInstanceDiscoveryMockHandler(discoveryEndpoint, jsonResponse)); } Task <AuthenticationResult> task = app .AcquireTokenSilent( TestConstants.s_scope.ToArray(), new Account(TestConstants.s_userIdentifier, TestConstants.DisplayableId, null)) .WithAuthority(app.Authority, false) .WithForceRefresh(false) .ExecuteAsync(CancellationToken.None); AuthenticationResult result = task.Result; Assert.IsNotNull(result); Assert.AreEqual(TestConstants.DisplayableId, result.Account.Username); Assert.AreEqual(TestConstants.s_scope.AsSingleString(), result.Scopes.AsSingleString()); Assert.AreEqual(2, app.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); Assert.AreEqual(1, app.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); Assert.IsNotNull(receiver.EventsReceived.Find(anEvent => // Expect finding such an event anEvent[EventBase.EventNameKey].EndsWith("api_event") && anEvent[ApiEvent.WasSuccessfulKey] == "true" && anEvent[MsalTelemetryBlobEventNames.ApiIdConstStrKey] == "1007")); } }
private static PublicClientApplication SetupPca(MockHttpAndServiceBundle harness) { Trace.WriteLine("1. Setup an app with a token cache with one AT"); PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithHttpManager(harness.HttpManager) .BuildConcrete(); TokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor, addSecondAt: false); return(app); }
public async Task ForceRefreshParameterTrueTestAsync() { await RunWithMockHttpAsync( async (httpManager, serviceBundle, receiver) => { httpManager.AddInstanceDiscoveryMockHandler(); var cache = new TokenCache(); _tokenCacheHelper.PopulateCache(cache.TokenCacheAccessor); string authority = Authority.CreateAuthority(serviceBundle, MsalTestConstants.AuthorityTestTenant, false) .CanonicalAuthority; var app = new ConfidentialClientApplication( serviceBundle, MsalTestConstants.ClientId, authority, MsalTestConstants.RedirectUri, new ClientCredential(MsalTestConstants.ClientSecret), null, cache) { ValidateAuthority = false }; httpManager.AddMockHandlerForTenantEndpointDiscovery(app.Authority); //add mock response for successful token retrival const string TokenRetrievedFromNetCall = "token retrieved from network call"; httpManager.AddMockHandler( new MockHttpMessageHandler { Method = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessfulClientCredentialTokenResponseMessage(TokenRetrievedFromNetCall) }); var result = await app.AcquireTokenForClientAsync(MsalTestConstants.Scope, true).ConfigureAwait(false); Assert.AreEqual(TokenRetrievedFromNetCall, result.AccessToken); // make sure token in Cache was updated ICollection <MsalAccessTokenCacheItem> accessTokens = cache.GetAllAccessTokensForClient(new RequestContext(null, new MsalLogger(Guid.NewGuid(), null))); var accessTokenInCache = accessTokens .Where(item => ScopeHelper.ScopeContains(item.ScopeSet, MsalTestConstants.Scope)) .ToList().FirstOrDefault(); Assert.AreEqual(TokenRetrievedFromNetCall, accessTokenInCache.Secret); Assert.IsNotNull( receiver.EventsReceived.Find( anEvent => // Expect finding such an event anEvent[EventBase.EventNameKey].EndsWith("api_event") && anEvent[ApiEvent.WasSuccessfulKey] == "true" && anEvent[ApiEvent.ApiIdKey] == "727")); }).ConfigureAwait(false); }
public async Task ForceRefreshParameterTrueTestAsync() { var receiver = new MyReceiver(); using (var httpManager = new MockHttpManager()) { httpManager.AddInstanceDiscoveryMockHandler(); var app = ConfidentialClientApplicationBuilder .Create(MsalTestConstants.ClientId) .WithAuthority(new Uri(MsalTestConstants.AuthorityTestTenant), true) .WithRedirectUri(MsalTestConstants.RedirectUri) .WithClientSecret(MsalTestConstants.ClientSecret) .WithHttpManager(httpManager) .WithTelemetry(receiver.HandleTelemetryEvents) .BuildConcrete(); _tokenCacheHelper.PopulateCache(app.AppTokenCacheInternal.Accessor); httpManager.AddMockHandlerForTenantEndpointDiscovery(app.Authority); // add mock response for successful token retrieval const string TokenRetrievedFromNetCall = "token retrieved from network call"; httpManager.AddMockHandler( new MockHttpMessageHandler { ExpectedMethod = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessfulClientCredentialTokenResponseMessage(TokenRetrievedFromNetCall) }); var result = await app .AcquireTokenForClient(MsalTestConstants.Scope) .WithForceRefresh(true) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreEqual(TokenRetrievedFromNetCall, result.AccessToken); // make sure token in Cache was updated var accessTokens = await app.AppTokenCacheInternal.GetAllAccessTokensAsync(true).ConfigureAwait(false); var accessTokenInCache = accessTokens .Where(item => ScopeHelper.ScopeContains(item.ScopeSet, MsalTestConstants.Scope)) .ToList().FirstOrDefault(); Assert.AreEqual(TokenRetrievedFromNetCall, accessTokenInCache.Secret); Assert.IsNotNull( receiver.EventsReceived.Find( anEvent => // Expect finding such an event anEvent[EventBase.EventNameKey].EndsWith("api_event") && anEvent[ApiEvent.WasSuccessfulKey] == "true" && anEvent[MsalTelemetryBlobEventNames.ApiIdConstStrKey] == "1004")); } }
public void AcquireTokenSilentScopeAndUserOverloadWithNoMatchingScopesInCacheTest() { // this test ensures that the API can // get authority (if unique) from the cache entries where scope does not match. // it should only happen for case where no authority is passed. PublicClientApplication app = new PublicClientApplication(TestConstants.ClientId) { ValidateAuthority = false }; cache = new TokenCache() { ClientId = TestConstants.ClientId }; //add mock response for tenant endpoint discovery HttpMessageHandlerFactory.AddMockHandler(new MockHttpMessageHandler { Method = HttpMethod.Get, ResponseMessage = MockHelpers.CreateOpenIdConfigurationResponse(TestConstants.AuthorityHomeTenant) }); HttpMessageHandlerFactory.AddMockHandler(new MockHttpMessageHandler() { Method = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage(TestConstants.UniqueId, TestConstants.DisplayableId, TestConstants.ScopeForAnotherResource.ToArray()) }); app.UserTokenCache = cache; TokenCacheHelper.PopulateCache(cache.TokenCacheAccessor); cache.TokenCacheAccessor.AccessTokenCacheDictionary.Remove(new AccessTokenCacheKey( TestConstants.AuthorityGuestTenant, TestConstants.ScopeForAnotherResource, TestConstants.ClientId, TestConstants.UserIdentifier).ToString()); Task <AuthenticationResult> task = app.AcquireTokenSilentAsync(TestConstants.ScopeForAnotherResource.ToArray(), new User() { DisplayableId = TestConstants.DisplayableId, Identifier = TestConstants.UserIdentifier, }); AuthenticationResult result = task.Result; Assert.IsNotNull(result); Assert.AreEqual(TestConstants.DisplayableId, result.User.DisplayableId); Assert.AreEqual(TestConstants.ScopeForAnotherResource.AsSingleString(), result.Scopes.AsSingleString()); Assert.AreEqual(2, cache.TokenCacheAccessor.GetAllAccessTokensAsString().Count()); }
public void AcquireTokenSilentScopeAndUserOverloadWithNoMatchingScopesInCacheTest() { // this test ensures that the API can // get authority (if unique) from the cache entries where scope does not match. // it should only happen for case where no authority is passed. using (var httpManager = new MockHttpManager()) { httpManager.AddInstanceDiscoveryMockHandler(); PublicClientApplication app = PublicClientApplicationBuilder.Create(MsalTestConstants.ClientId) .WithAuthority(new Uri(ClientApplicationBase.DefaultAuthority), true) .WithHttpManager(httpManager) .WithTelemetry(new TraceTelemetryConfig()) .BuildConcrete(); _tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor); app.UserTokenCacheInternal.Accessor.DeleteAccessToken( new MsalAccessTokenCacheKey( MsalTestConstants.ProductionPrefNetworkEnvironment, MsalTestConstants.Utid, MsalTestConstants.UserIdentifier, MsalTestConstants.ClientId, MsalTestConstants.ScopeForAnotherResourceStr)); Task <AuthenticationResult> task = app .AcquireTokenSilent( MsalTestConstants.ScopeForAnotherResource.ToArray(), new Account(MsalTestConstants.UserIdentifier, MsalTestConstants.DisplayableId, null)) .ExecuteAsync(CancellationToken.None); AuthenticationResult result = task.Result; Assert.IsNotNull(result); Assert.AreEqual(MsalTestConstants.DisplayableId, result.Account.Username); Assert.AreEqual(MsalTestConstants.ScopeForAnotherResource.AsSingleString(), result.Scopes.AsSingleString()); Assert.AreEqual(2, app.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); } }
public async Task RefreshReasonExpired_AcquireTokenSilent_Async() { using (var harness = CreateTestHarness()) { harness.HttpManager.AddInstanceDiscoveryMockHandler(); harness.HttpManager.AddMockHandler( new MockHttpMessageHandler() { ExpectedMethod = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage( TestConstants.Uid, TestConstants.DisplayableId, TestConstants.s_scope.ToArray()) }); PublicClientApplication pca = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithAuthority(new Uri(ClientApplicationBase.DefaultAuthority), false) .WithHttpManager(harness.HttpManager) .BuildConcrete(); TokenCacheHelper.PopulateCache(pca.UserTokenCacheInternal.Accessor); //expire access tokens TokenCacheHelper.ExpireAllAccessTokens(pca.UserTokenCacheInternal); // Act - AcquireTokenForClient returns result from IDP. AuthenticationResult result = await pca.AcquireTokenSilent( TestConstants.s_scope.ToArray(), TestConstants.DisplayableId) .ExecuteAsync() .ConfigureAwait(false); //Token should have refreshed due to expiration. Assert.IsNotNull(result); Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); Assert.AreEqual(CacheRefreshReason.Expired, result.AuthenticationResultMetadata.CacheRefreshReason); // Act - AcquireTokenForClient returns result from Cache. result = await pca.AcquireTokenSilent( TestConstants.s_scope.ToArray(), TestConstants.DisplayableId) .ExecuteAsync() .ConfigureAwait(false); //Token should have come from cache and cache should not have been refreshed. Assert.IsNotNull(result); Assert.AreEqual(TokenSource.Cache, result.AuthenticationResultMetadata.TokenSource); Assert.AreEqual(CacheRefreshReason.NotApplicable, result.AuthenticationResultMetadata.CacheRefreshReason); } }
public void AcquireTokenSilentForceRefreshTest() { 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) }); cache = new TokenCache() { ClientId = TestConstants.ClientId }; app.UserTokenCache = cache; TokenCacheHelper.PopulateCache(cache.TokenCacheAccessor); HttpMessageHandlerFactory.AddMockHandler(new MockHttpMessageHandler() { Method = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage(TestConstants.UniqueId, TestConstants.DisplayableId, TestConstants.Scope.ToArray()) }); Task <AuthenticationResult> task = app.AcquireTokenSilentAsync(TestConstants.Scope.ToArray(), new User() { DisplayableId = TestConstants.DisplayableId, Identifier = TestConstants.UserIdentifier, }, null, true); AuthenticationResult result = task.Result; Assert.IsNotNull(result); Assert.AreEqual(TestConstants.DisplayableId, result.User.DisplayableId); Assert.AreEqual( TestConstants.Scope.ToArray().AsSingleString(), result.Scopes.AsSingleString()); Assert.AreEqual(2, cache.TokenCacheAccessor.AccessTokenCacheDictionary.Count); Assert.AreEqual(1, cache.TokenCacheAccessor.RefreshTokenCacheDictionary.Count); Assert.IsTrue(HttpMessageHandlerFactory.IsMocksQueueEmpty, "All mocks should have been consumed"); }
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"); }
public void GetAccountsAndSignThemOutTest() { PublicClientApplication app = PublicClientApplicationBuilder.Create(MsalTestConstants.ClientId).BuildConcrete(); var tokenCacheHelper = new TokenCacheHelper(); tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor); foreach (var user in app.GetAccountsAsync().Result) { app.RemoveAsync(user).Wait(); } Assert.AreEqual(0, app.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); Assert.AreEqual(0, app.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); }