public async Task TestSendGetWithHttp500TypeFailureAsync() { using (var httpManager = new MockHttpManager()) { httpManager.AddResiliencyMessageMockHandler(HttpMethod.Get, HttpStatusCode.GatewayTimeout); httpManager.AddResiliencyMessageMockHandler(HttpMethod.Get, HttpStatusCode.InternalServerError); try { var msalHttpResponse = await httpManager.SendGetAsync( new Uri(TestConstants.AuthorityHomeTenant + "oauth2/token"), null, Substitute.For <ICoreLogger>()) .ConfigureAwait(false); Assert.Fail("request should have failed"); } catch (MsalServiceException exc) { Assert.IsNotNull(exc); Assert.AreEqual(MsalError.ServiceNotAvailable, exc.ErrorCode); } } }
public async Task B2C_NoScopes_NoAccessToken_Async() { using (var httpManager = new MockHttpManager()) { PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithAuthority(new Uri(TestConstants.B2CLoginAuthority), true) .WithHttpManager(httpManager) .BuildConcrete(); MsalMockHelpers.ConfigureMockWebUI( app.ServiceBundle, AuthorizationResult.FromUri(app.AppConfig.RedirectUri + "?code=some-code")); // Arrange 1 - interactive call with 0 scopes httpManager.AddSuccessTokenResponseMockHandlerForPost( TestConstants.B2CLoginAuthority, responseMessage: MockHelpers.CreateSuccessResponseMessage(MockHelpers.B2CTokenResponseWithoutAT)); // Act AuthenticationResult result = await app .AcquireTokenInteractive(null) // no scopes -> no Access Token! .ExecuteAsync() .ConfigureAwait(false); // Assert AssertNoAccessToken(result); Assert.AreEqual(0, httpManager.QueueSize); var ex = await AssertException.TaskThrowsAsync <MsalUiRequiredException>(() => app.AcquireTokenSilent(null, result.Account).ExecuteAsync() ).ConfigureAwait(false); Assert.AreEqual(MsalError.ScopesRequired, ex.ErrorCode); Assert.AreEqual(UiRequiredExceptionClassification.AcquireTokenSilentFailed, ex.Classification); } }
public async Task TokensAreInterchangable_NonRegional_To_Regional_Async() { using (var httpManager = new MockHttpManager()) { httpManager.AddInstanceDiscoveryMockHandler(); httpManager.AddMockHandler(CreateTokenResponseHttpHandler(false)); IConfidentialClientApplication appWithRegion = CreateCca( httpManager, ConfidentialClientApplication.AttemptRegionDiscovery); InMemoryTokenCache memoryTokenCache = new InMemoryTokenCache(); memoryTokenCache.Bind(appWithRegion.AppTokenCache); IConfidentialClientApplication appWithoutRegion = CreateCca( httpManager, null); memoryTokenCache.Bind(appWithoutRegion.AppTokenCache); AuthenticationResult result = await appWithoutRegion .AcquireTokenForClient(TestConstants.s_scope) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.IsTrue(result.AuthenticationResultMetadata.TokenSource == TokenSource.IdentityProvider); httpManager.AddRegionDiscoveryMockHandler("uscentral"); // when switching to non-region, token is found in the cache result = await appWithRegion .AcquireTokenForClient(TestConstants.s_scope) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.IsTrue(result.AuthenticationResultMetadata.TokenSource == TokenSource.Cache); } }
public void GetAuthorizationRequestUrlCustomRedirectUriTest() { using (var httpManager = new MockHttpManager()) { httpManager.AddInstanceDiscoveryMockHandler(); var app = ConfidentialClientApplicationBuilder.Create(MsalTestConstants.ClientId) .WithAuthority(new Uri(ClientApplicationBase.DefaultAuthority), true) .WithRedirectUri(MsalTestConstants.RedirectUri) .WithClientSecret(MsalTestConstants.ClientSecret) .WithHttpManager(httpManager) .BuildConcrete(); httpManager.AddMockHandlerForTenantEndpointDiscovery(MsalTestConstants.AuthorityGuestTenant); const string CustomRedirectUri = "custom://redirect-uri"; Task <Uri> task = app .GetAuthorizationRequestUrl(MsalTestConstants.Scope) .WithRedirectUri(CustomRedirectUri) .WithLoginHint(MsalTestConstants.DisplayableId) .WithExtraQueryParameters("extra=qp") .WithExtraScopesToConsent(MsalTestConstants.ScopeForAnotherResource) .WithAuthority(MsalTestConstants.AuthorityGuestTenant) .ExecuteAsync(CancellationToken.None); var uri = task.Result; Assert.IsNotNull(uri); Assert.IsTrue( uri.AbsoluteUri.StartsWith(MsalTestConstants.AuthorityGuestTenant, StringComparison.CurrentCulture)); Dictionary <string, string> qp = CoreHelpers.ParseKeyValueList(uri.Query.Substring(1), '&', true, null); ValidateCommonQueryParams(qp, CustomRedirectUri); Assert.AreEqual("offline_access openid profile r1/scope1 r1/scope2 r2/scope1 r2/scope2", qp["scope"]); Assert.IsFalse(qp.ContainsKey("client_secret")); Assert.AreEqual("qp", qp["extra"]); } }
public void UnifiedCache_ProcessAdalDictionaryForDuplicateKeyTest() { using (var httpManager = new MockHttpManager()) { var serviceBundle = ServiceBundle.CreateWithCustomHttpManager(httpManager); var app = new PublicClientApplication( serviceBundle, MsalTestConstants.ClientId, ClientApplicationBase.DefaultAuthority) { UserTokenCache = { LegacyCachePersistence = new TestLegacyCachePersistance() } }; CreateAdalCache(app.UserTokenCache.LegacyCachePersistence, MsalTestConstants.Scope.ToString()); var adalUsers = CacheFallbackOperations.GetAllAdalUsersForMsal( app.UserTokenCache.LegacyCachePersistence, MsalTestConstants.ClientId); CreateAdalCache(app.UserTokenCache.LegacyCachePersistence, "user.read"); var adalUsers2 = CacheFallbackOperations.GetAllAdalUsersForMsal( app.UserTokenCache.LegacyCachePersistence, MsalTestConstants.ClientId); Assert.AreEqual(adalUsers.ClientInfoUsers.Keys.First(), adalUsers2.ClientInfoUsers.Keys.First()); app.UserTokenCache.TokenCacheAccessor.ClearAccessTokens(); app.UserTokenCache.TokenCacheAccessor.ClearRefreshTokens(); } }
/// <summary> /// Generate a certificate. Create a Confidential Client Application with that certificate and /// an AcquireTokenForClient call to benchmark. /// </summary> public CryptoManagerTests() { _httpManager = new MockHttpManager(); _httpManager.MessageHandlerFunc = () => new MockHttpMessageHandler() { ExpectedMethod = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessfulClientCredentialTokenResponseMessage() }; _requests = new AcquireTokenForClientParameterBuilder[AppsCount]; for (int i = 0; i < AppsCount; i++) { X509Certificate2 certificate = CreateCertificate("CN=rsa2048", RSA.Create(2048), HashAlgorithmName.SHA256, null); _cca = ConfidentialClientApplicationBuilder .Create(TestConstants.ClientId) .WithAuthority(new Uri(TestConstants.AuthorityTestTenant)) .WithRedirectUri(TestConstants.RedirectUri) .WithCertificate(certificate) .WithHttpManager(_httpManager) .BuildConcrete(); AddHostToInstanceCache(_cca.ServiceBundle, TestConstants.ProductionPrefNetworkEnvironment); _requests[_requestIdx] = _cca.AcquireTokenForClient(TestConstants.s_scope) .WithForceRefresh(true); } }
public void B2CLoginAuthorityCreateAuthority() { using (var httpManager = new MockHttpManager()) { var serviceBundle = ServiceBundle.CreateWithCustomHttpManager(httpManager); // add mock response for tenant endpoint discovery httpManager.AddMockHandler( new MockHttpMessageHandler { Method = HttpMethod.Get, Url = "https://mytenant.com.b2clogin.com/tfp/mytenant.com/my-policy/v2.0/.well-known/openid-configuration", ResponseMessage = MockHelpers.CreateSuccessResponseMessage( File.ReadAllText(ResourceHelper.GetTestResourceRelativePath("OpenidConfiguration-B2CLogin.json"))) }); Authority instance = Authority.CreateAuthority(serviceBundle, "https://mytenant.com.b2clogin.com/tfp/mytenant.com/my-policy/", true); Assert.IsNotNull(instance); Assert.AreEqual(instance.AuthorityType, AuthorityType.B2C); Task.Run( async() => { await instance.ResolveEndpointsAsync( null, new RequestContext(null, new MsalLogger(Guid.NewGuid(), null))).ConfigureAwait(false); }).GetAwaiter().GetResult(); Assert.AreEqual( "https://mytenant.com.b2clogin.com/6babcaad-604b-40ac-a9d7-9fd97c0b779f/my-policy/oauth2/v2.0/authorize", instance.AuthorizationEndpoint); Assert.AreEqual( "https://mytenant.com.b2clogin.com/6babcaad-604b-40ac-a9d7-9fd97c0b779f/my-policy/oauth2/v2.0/token", instance.TokenEndpoint); Assert.AreEqual("https://mytenant.com.b2clogin.com/6babcaad-604b-40ac-a9d7-9fd97c0b779f/v2.0/", instance.SelfSignedJwtAudience); } }
public async Task AcquireTokenSilent_LoginHint_MultipleAccountsAsync() { var receiver = new MyReceiver(); using (var httpManager = new MockHttpManager()) { PublicClientApplication app = PublicClientApplicationBuilder.Create(MsalTestConstants.ClientId) .WithAuthority(new Uri(MsalTestConstants.AuthorityTestTenant), true) .WithHttpManager(httpManager) .WithTelemetry(receiver.HandleTelemetryEvents) .BuildConcrete(); _tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor, "uid1", "utid"); _tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor, "uid2", "utid"); var exception = await AssertException.TaskThrowsAsync <MsalUiRequiredException>(async() => await app.AcquireTokenSilent( MsalTestConstants.Scope.ToArray(), MsalTestConstants.DisplayableId) .WithAuthority(app.Authority, false) .ExecuteAsync().ConfigureAwait(false)).ConfigureAwait(false); Assert.AreEqual(MsalError.MultipleAccountsForLoginHint, exception.ErrorCode); } }
public async Task AcquireTokenSilent_LoginHintAsync() { using (var httpManager = new MockHttpManager()) { PublicClientApplication app = PublicClientApplicationBuilder.Create(MsalTestConstants.ClientId) .WithAuthority(new Uri(MsalTestConstants.AuthorityTestTenant), true) .WithHttpManager(httpManager) .BuildConcrete(); _tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor); httpManager.AddInstanceDiscoveryMockHandler(); AuthenticationResult result = await app.AcquireTokenSilent( MsalTestConstants.Scope.ToArray(), MsalTestConstants.DisplayableId) .WithAuthority(app.Authority, false) .ExecuteAsync() .ConfigureAwait(false); Assert.IsNotNull(result); Assert.AreEqual(MsalTestConstants.DisplayableId, result.Account.Username); Assert.AreEqual(MsalTestConstants.Scope.AsSingleString(), result.Scopes.AsSingleString()); } }
public async Task ManagedUsernameSecureStringPasswordAcquireTokenTestAsync() { using (var httpManager = new MockHttpManager()) { httpManager.AddInstanceDiscoveryMockHandler(); AddMockResponseforManagedAccounts(httpManager); httpManager.AddMockHandler( new MockHttpMessageHandler { ExpectedMethod = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage(), ExpectedPostData = new Dictionary <string, string> { { "grant_type", "password" }, { "username", TestConstants.s_user.Username }, } }); PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs) .WithHttpManager(httpManager) .WithTelemetry(new TraceTelemetryConfig()) .BuildConcrete(); AuthenticationResult result = await app.AcquireTokenByUsernamePassword( TestConstants.s_scope, TestConstants.s_user.Username, _secureString).ExecuteAsync(CancellationToken.None).ConfigureAwait(false); Assert.IsNotNull(result); Assert.AreEqual("some-access-token", result.AccessToken); Assert.IsNotNull(result.Account); Assert.AreEqual(TestConstants.s_user.Username, result.Account.Username); } }
public void FailedTenantDiscoveryMissingEndpointsTest() { using (var httpManager = new MockHttpManager()) { var serviceBundle = ServiceBundle.CreateWithCustomHttpManager(httpManager); //add mock response for tenant endpoint discovery httpManager.AddMockHandler( new MockHttpMessageHandler { Method = HttpMethod.Get, Url = "https://fs.contoso.com/adfs/.well-known/openid-configuration", ResponseMessage = MockHelpers.CreateSuccessResponseMessage( ResourceHelper.GetTestResourceRelativePath(File.ReadAllText("OpenidConfiguration-MissingFields-OnPremise.json"))) }); Authority instance = Authority.CreateAuthority(serviceBundle, CoreTestConstants.OnPremiseAuthority, false); Assert.IsNotNull(instance); Assert.AreEqual(instance.AuthorityType, AuthorityType.Adfs); try { Task.Run( async() => { await instance.ResolveEndpointsAsync( CoreTestConstants.FabrikamDisplayableId, new RequestContext(null, new MsalLogger(Guid.NewGuid(), null))).ConfigureAwait(false); }).GetAwaiter().GetResult(); Assert.Fail("validation should have failed here"); } catch (MsalServiceException exc) { Assert.AreEqual(CoreErrorCodes.TenantDiscoveryFailedError, exc.ErrorCode); } } }
[WorkItem(1403)] // https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/1403 public async Task FooAsync() { using (var httpManager = new MockHttpManager()) { httpManager.AddInstanceDiscoveryMockHandler(); var app = ConfidentialClientApplicationBuilder.Create(TestConstants.ClientId) .WithClientSecret(TestConstants.ClientSecret) .WithHttpManager(httpManager) .BuildConcrete(); var handler = httpManager.AddMockHandlerSuccessfulClientCredentialTokenResponseMessage(); handler.ExpectedPostData = new Dictionary <string, string>() { // Bug 1403: Do not add reserved scopes profile, offline_access and openid to Confidential Client request { "scope", TestConstants.s_scope.AsSingleString() } }; var result = await app.AcquireTokenForClient(TestConstants.s_scope.ToArray()) .WithAuthority(TestConstants.AuthorityUtidTenant) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); } }
// Test for https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/2514 public async Task AuthorityValidationHappensOnNonRegionalAuthorityAsync() { using (var httpManager = new MockHttpManager()) { var handler = new MockHttpMessageHandler() { ExpectedUrl = "https://login.microsoftonline.com/common/discovery/instance", ExpectedMethod = HttpMethod.Get, ResponseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent(TestConstants.DiscoveryFailedResponse) } }; httpManager.AddMockHandler(handler); var app = ConfidentialClientApplicationBuilder .Create(TestConstants.ClientId) .WithAuthority("https://invalid.com/common") .WithRedirectUri(TestConstants.RedirectUri) .WithHttpManager(httpManager) .WithClientSecret(TestConstants.ClientSecret) .Build(); // Act var ex = await AssertException.TaskThrowsAsync <MsalServiceException>(() => app .AcquireTokenForClient(TestConstants.s_scope) .ExecuteAsync()) .ConfigureAwait(false); // Assert Assert.AreEqual(MsalError.InvalidInstance, ex.ErrorCode); var qp = CoreHelpers.ParseKeyValueList(handler.ActualRequestMessage.RequestUri.Query.Substring(1), '&', true, null); Assert.AreEqual("https://invalid.com/common/oauth2/v2.0/authorize", qp["authorization_endpoint"]); } }
private static async Task RunObo_Async(MockHttpManager httpManager, ConfidentialClientApplication app) { httpManager.AddSuccessTokenResponseMockHandlerForPost(); UserAssertion userAssertion = new UserAssertion(TestConstants.DefaultAccessToken); var result = await app.AcquireTokenOnBehalfOf(TestConstants.s_scope, userAssertion).ExecuteAsync().ConfigureAwait(false); Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); // get AT from cache result = await app.AcquireTokenOnBehalfOf(TestConstants.s_scope, userAssertion).ExecuteAsync().ConfigureAwait(false); Assert.AreEqual(TokenSource.Cache, result.AuthenticationResultMetadata.TokenSource); // get AT via OBO flow (no RT cached for OBO) TokenCacheHelper.ExpireAllAccessTokens(app.UserTokenCacheInternal); var handler = httpManager.AddSuccessTokenResponseMockHandlerForPost(); handler.ExpectedPostData = new Dictionary <string, string> { { OAuth2Parameter.GrantType, OAuth2GrantType.JwtBearer } }; result = await app.AcquireTokenOnBehalfOf(TestConstants.s_scope, userAssertion).ExecuteAsync().ConfigureAwait(false); Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); }
public async Task AuthorityMigrationTestAsync() { // make sure that for all network calls "preferred_cache" environment is used // (it is taken from metadata in instance discovery response), // except very first network call - instance discovery using (var httpManager = new MockHttpManager()) { var authorityUri = new Uri( string.Format( CultureInfo.InvariantCulture, "https://{0}/common", TestConstants.ProductionNotPrefEnvironmentAlias)); httpManager.AddInstanceDiscoveryMockHandler(authorityUri.AbsoluteUri); PublicClientApplication app = PublicClientApplicationBuilder .Create(TestConstants.ClientId) .WithAuthority(authorityUri, true) .WithHttpManager(httpManager) .WithUserTokenLegacyCachePersistenceForTest(new TestLegacyCachePersistance()) .WithTelemetry(new TraceTelemetryConfig()) .WithDebugLoggingCallback() .BuildConcrete(); // mock for openId config request httpManager.AddMockHandler(new MockHttpMessageHandler { ExpectedUrl = string.Format(CultureInfo.InvariantCulture, "https://{0}/common/v2.0/.well-known/openid-configuration", TestConstants.ProductionPrefNetworkEnvironment), ExpectedMethod = HttpMethod.Get, ResponseMessage = MockHelpers.CreateOpenIdConfigurationResponse(TestConstants.AuthorityHomeTenant) }); // mock webUi authorization MsalMockHelpers.ConfigureMockWebUI( app.ServiceBundle.PlatformProxy, AuthorizationResult.FromUri(app.AppConfig.RedirectUri + "?code=some-code"), null, TestConstants.ProductionPrefNetworkEnvironment); // mock token request httpManager.AddMockHandler(new MockHttpMessageHandler { ExpectedUrl = string.Format(CultureInfo.InvariantCulture, "https://{0}/home/oauth2/v2.0/token", TestConstants.ProductionPrefNetworkEnvironment), ExpectedMethod = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage() }); AuthenticationResult result = app.AcquireTokenInteractive(TestConstants.s_scope).ExecuteAsync(CancellationToken.None).Result; // make sure that all cache entities are stored with "preferred_cache" environment // (it is taken from metadata in instance discovery response) await ValidateCacheEntitiesEnvironmentAsync(app.UserTokenCacheInternal, TestConstants.ProductionPrefCacheEnvironment).ConfigureAwait(false); // silent request targeting at, should return at from cache for any environment alias foreach (var envAlias in TestConstants.s_prodEnvAliases) { result = await app .AcquireTokenSilent( TestConstants.s_scope, app.GetAccountsAsync().Result.First()) .WithAuthority(string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/", envAlias, TestConstants.Utid)) .WithForceRefresh(false) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.IsNotNull(result); } // mock for openId config request for tenant specific authority httpManager.AddMockHandler(new MockHttpMessageHandler { ExpectedUrl = string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/v2.0/.well-known/openid-configuration", TestConstants.ProductionPrefNetworkEnvironment, TestConstants.Utid), ExpectedMethod = HttpMethod.Get, ResponseMessage = MockHelpers.CreateOpenIdConfigurationResponse(TestConstants.AuthorityUtidTenant) }); // silent request targeting rt should find rt in cache for authority with any environment alias foreach (var envAlias in TestConstants.s_prodEnvAliases) { result = null; httpManager.AddMockHandler(new MockHttpMessageHandler() { ExpectedUrl = string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/oauth2/v2.0/token", TestConstants.ProductionPrefNetworkEnvironment, TestConstants.Utid), ExpectedMethod = HttpMethod.Post, ExpectedPostData = new Dictionary <string, string>() { { "grant_type", "refresh_token" } }, // return not retriable status code ResponseMessage = MockHelpers.CreateInvalidGrantTokenResponseMessage() }); try { result = await app .AcquireTokenSilent( TestConstants.s_scopeForAnotherResource, (await app.GetAccountsAsync().ConfigureAwait(false)).First()) .WithAuthority(string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/", envAlias, TestConstants.Utid)) .WithForceRefresh(false) .ExecuteAsync(CancellationToken.None).ConfigureAwait(false); } catch (MsalUiRequiredException) { } catch (Exception) { Assert.Fail(); } Assert.IsNull(result); } } }
internal static void MockInstanceDiscoveryAndOpenIdRequest(MockHttpManager mockHttpManager) { mockHttpManager.AddInstanceDiscoveryMockHandler(); mockHttpManager.AddMockHandlerForTenantEndpointDiscovery(TestConstants.AuthorityHomeTenant); }
private void Init(MockHttpManager httpManager) { httpManager.AddInstanceDiscoveryMockHandler(); }
public async Task ConfidentialClientUsingAdfsAsync() { using (var httpManager = new MockHttpManager()) { var app = ConfidentialClientApplicationBuilder.Create(MsalTestConstants.ClientId) .WithAuthority(new Uri(MsalTestConstants.OnPremiseAuthority), true) .WithRedirectUri(MsalTestConstants.RedirectUri) .WithClientSecret(MsalTestConstants.ClientSecret) .WithHttpManager(httpManager) .BuildConcrete(); httpManager.AddMockHandler( new MockHttpMessageHandler { ExpectedMethod = HttpMethod.Get, ExpectedUrl = "https://fs.contoso.com/.well-known/webfinger", ExpectedQueryParams = new Dictionary <string, string> { { "resource", "https://fs.contoso.com" }, { "rel", "http://schemas.microsoft.com/rel/trusted-realm" } }, ResponseMessage = MockHelpers.CreateSuccessWebFingerResponseMessage("https://fs.contoso.com") }); httpManager.AddMockHandler(new MockHttpMessageHandler { ExpectedMethod = HttpMethod.Get, ResponseMessage = MockHelpers.CreateOpenIdConfigurationResponse(MsalTestConstants.OnPremiseAuthority) }); httpManager.AddMockHandlerSuccessfulClientCredentialTokenResponseMessage(); var result = await app.AcquireTokenForClient(MsalTestConstants.Scope.ToArray()).ExecuteAsync().ConfigureAwait(false); Assert.IsNotNull(result); Assert.IsNotNull("header.payload.signature", result.AccessToken); Assert.AreEqual(MsalTestConstants.Scope.AsSingleString(), result.Scopes.AsSingleString()); // make sure user token cache is empty Assert.AreEqual(0, app.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); Assert.AreEqual(0, app.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); // check app token cache count to be 1 Assert.AreEqual(1, app.AppTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); Assert.AreEqual(0, app.AppTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); // no refresh tokens are returned // call AcquireTokenForClientAsync again to get result back from the cache result = await app.AcquireTokenForClient(MsalTestConstants.Scope.ToArray()).ExecuteAsync().ConfigureAwait(false); Assert.IsNotNull(result); Assert.IsNotNull("header.payload.signature", result.AccessToken); Assert.AreEqual(MsalTestConstants.Scope.AsSingleString(), result.Scopes.AsSingleString()); // make sure user token cache is empty Assert.AreEqual(0, app.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); Assert.AreEqual(0, app.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); // check app token cache count to be 1 Assert.AreEqual(1, app.AppTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); Assert.AreEqual(0, app.AppTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); // no refresh tokens are returned } }
[WorkItem(695)] // Fix for https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/695 public void AcquireTokenSilentForceRefreshMultipleTenantsTest() { using (var httpManager = new MockHttpManager()) { PublicClientApplication app = PublicClientApplicationBuilder.Create(MsalTestConstants.ClientId) .WithAuthority(new Uri(ClientApplicationBase.DefaultAuthority), true) .WithHttpManager(httpManager) .BuildConcrete(); var tokenCacheHelper = new TokenCacheHelper(); tokenCacheHelper.PopulateCacheWithOneAccessToken(app.UserTokenCacheInternal.Accessor); httpManager.AddInstanceDiscoveryMockHandler(); httpManager.AddMockHandlerForTenantEndpointDiscovery(MsalTestConstants.AuthorityCommonTenant); httpManager.AddMockHandler( new MockHttpMessageHandler() { ExpectedMethod = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage( MsalTestConstants.UniqueId, MsalTestConstants.DisplayableId, MsalTestConstants.Scope.ToArray()) }); // ForceRefresh=true, so skip cache lookup of Access Token // Use refresh token to acquire a new Access Token Task <AuthenticationResult> task = app .AcquireTokenSilent( MsalTestConstants.Scope.ToArray(), new Account(MsalTestConstants.UserIdentifier, MsalTestConstants.DisplayableId, null)) .WithAuthority(MsalTestConstants.AuthorityCommonTenant) .WithForceRefresh(true) .ExecuteAsync(CancellationToken.None); AuthenticationResult result = task.Result; Assert.IsNotNull(result); Assert.AreEqual(MsalTestConstants.DisplayableId, result.Account.Username); Assert.AreEqual(MsalTestConstants.Scope.ToArray().AsSingleString(), result.Scopes.AsSingleString()); Assert.AreEqual(1, app.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); Assert.AreEqual(1, app.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); httpManager.AddMockHandlerForTenantEndpointDiscovery(MsalTestConstants.AuthorityGuidTenant2); httpManager.AddMockHandler( new MockHttpMessageHandler() { ExpectedMethod = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage( MsalTestConstants.UniqueId, MsalTestConstants.DisplayableId, MsalTestConstants.Scope.ToArray()) }); Task <AuthenticationResult> task2 = app .AcquireTokenSilent( MsalTestConstants.Scope.ToArray(), new Account(MsalTestConstants.UserIdentifier, MsalTestConstants.DisplayableId, null)) .WithAuthority(MsalTestConstants.AuthorityGuidTenant2) .WithForceRefresh(true) .ExecuteAsync(CancellationToken.None); // Same user, scopes, clientId, but different authority // Should result in new AccessToken, but same refresh token AuthenticationResult result2 = task2.Result; Assert.IsNotNull(result2); Assert.AreEqual(MsalTestConstants.DisplayableId, result2.Account.Username); Assert.AreEqual(MsalTestConstants.Scope.ToArray().AsSingleString(), result2.Scopes.AsSingleString()); Assert.AreEqual(2, app.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); Assert.AreEqual(1, app.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); httpManager.AddMockHandlerForTenantEndpointDiscovery(MsalTestConstants.AuthorityGuidTenant); httpManager.AddMockHandler( new MockHttpMessageHandler() { ExpectedMethod = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage( MsalTestConstants.UniqueId, MsalTestConstants.DisplayableId, MsalTestConstants.Scope.ToArray()) }); // Same user, scopes, clientId, but different authority // Should result in new AccessToken, but same refresh token Task <AuthenticationResult> task3 = app .AcquireTokenSilent( MsalTestConstants.Scope.ToArray(), new Account(MsalTestConstants.UserIdentifier, MsalTestConstants.DisplayableId, null)) .WithAuthority(MsalTestConstants.AuthorityGuidTenant) .WithForceRefresh(true) .ExecuteAsync(CancellationToken.None); AuthenticationResult result3 = task3.Result; Assert.IsNotNull(result3); Assert.AreEqual(MsalTestConstants.DisplayableId, result3.Account.Username); Assert.AreEqual(MsalTestConstants.Scope.ToArray().AsSingleString(), result3.Scopes.AsSingleString()); Assert.AreEqual(3, app.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); Assert.AreEqual(1, app.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); // Use same authority as above, number of access tokens should remain constant httpManager.AddMockHandler( new MockHttpMessageHandler() { ExpectedMethod = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage( MsalTestConstants.UniqueId, MsalTestConstants.DisplayableId, MsalTestConstants.Scope.ToArray()) }); Task <AuthenticationResult> task4 = app .AcquireTokenSilent( MsalTestConstants.Scope.ToArray(), new Account(MsalTestConstants.UserIdentifier, MsalTestConstants.DisplayableId, null)) .WithAuthority(MsalTestConstants.AuthorityGuidTenant) .WithForceRefresh(true) .ExecuteAsync(CancellationToken.None); AuthenticationResult result4 = task4.Result; Assert.IsNotNull(result4); Assert.AreEqual(MsalTestConstants.DisplayableId, result4.Account.Username); Assert.AreEqual(MsalTestConstants.Scope.ToArray().AsSingleString(), result4.Scopes.AsSingleString()); Assert.AreEqual(3, app.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); Assert.AreEqual(1, app.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); } }
public void TestGetAccounts() { var tokenCacheHelper = new TokenCacheHelper(); using (var httpManager = new MockHttpManager()) { PublicClientApplication app = PublicClientApplicationBuilder.Create(MsalTestConstants.ClientId) .WithHttpManager(httpManager) .BuildConcrete(); IEnumerable <IAccount> accounts = app.GetAccountsAsync().Result; Assert.IsNotNull(accounts); Assert.IsFalse(accounts.Any()); tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor); accounts = app.GetAccountsAsync().Result; Assert.IsNotNull(accounts); Assert.AreEqual(1, accounts.Count()); var atItem = new MsalAccessTokenCacheItem( MsalTestConstants.ProductionPrefCacheEnvironment, MsalTestConstants.ClientId, MsalTestConstants.Scope.AsSingleString(), MsalTestConstants.Utid, null, new DateTimeOffset(DateTime.UtcNow + TimeSpan.FromSeconds(3600)), new DateTimeOffset(DateTime.UtcNow + TimeSpan.FromSeconds(7200)), MockHelpers.CreateClientInfo()); atItem.Secret = atItem.GetKey().ToString(); app.UserTokenCacheInternal.Accessor.SaveAccessToken(atItem); // another cache entry for different uid. user count should be 2. MsalRefreshTokenCacheItem rtItem = new MsalRefreshTokenCacheItem( MsalTestConstants.ProductionPrefCacheEnvironment, MsalTestConstants.ClientId, "someRT", MockHelpers.CreateClientInfo("uId1", "uTId1")); app.UserTokenCacheInternal.Accessor.SaveRefreshToken(rtItem); MsalIdTokenCacheItem idTokenCacheItem = new MsalIdTokenCacheItem( MsalTestConstants.ProductionPrefCacheEnvironment, MsalTestConstants.ClientId, MockHelpers.CreateIdToken(MsalTestConstants.UniqueId, MsalTestConstants.DisplayableId), MockHelpers.CreateClientInfo("uId1", "uTId1"), "uTId1"); app.UserTokenCacheInternal.Accessor.SaveIdToken(idTokenCacheItem); MsalAccountCacheItem accountCacheItem = new MsalAccountCacheItem( MsalTestConstants.ProductionPrefCacheEnvironment, null, MockHelpers.CreateClientInfo("uId1", "uTId1"), null, null, "uTId1", null, null); app.UserTokenCacheInternal.Accessor.SaveAccount(accountCacheItem); Assert.AreEqual(2, app.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); accounts = app.GetAccountsAsync().Result; Assert.IsNotNull(accounts); Assert.AreEqual(2, accounts.Count()); // scoped by env // another cache entry for different environment. user count should still be 2. Sovereign cloud user must not be returned rtItem = new MsalRefreshTokenCacheItem( MsalTestConstants.SovereignNetworkEnvironment, MsalTestConstants.ClientId, "someRT", MockHelpers.CreateClientInfo(MsalTestConstants.Uid + "more1", MsalTestConstants.Utid)); app.UserTokenCacheInternal.Accessor.SaveRefreshToken(rtItem); Assert.AreEqual(3, app.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); accounts = app.GetAccountsAsync().Result; Assert.IsNotNull(accounts); Assert.AreEqual(2, accounts.Count()); } }
public void AuthorityMigration_IntegrationTest() { // make sure that for all network calls "preferred_cache" environment is used // (it is taken from metadata in instance discovery response), // except very first network call - instance discovery using (var httpManager = new MockHttpManager()) { var serviceBundle = ServiceBundle.CreateWithCustomHttpManager(httpManager); TestInitialize(httpManager); PublicClientApplication app = new PublicClientApplication( serviceBundle, MsalTestConstants.ClientId, string.Format( CultureInfo.InvariantCulture, "https://{0}/common", MsalTestConstants.ProductionNotPrefEnvironmentAlias)) { UserTokenCache = { LegacyCachePersistence = new TestLegacyCachePersistance() } }; // mock for openId config request httpManager.AddMockHandler(new MockHttpMessageHandler { Url = string.Format(CultureInfo.InvariantCulture, "https://{0}/common/v2.0/.well-known/openid-configuration", MsalTestConstants.ProductionPrefNetworkEnvironment), Method = HttpMethod.Get, ResponseMessage = MockHelpers.CreateOpenIdConfigurationResponse(MsalTestConstants.AuthorityHomeTenant) }); // mock webUi authorization MsalMockHelpers.ConfigureMockWebUI(new AuthorizationResult(AuthorizationStatus.Success, app.RedirectUri + "?code=some-code"), null, MsalTestConstants.ProductionPrefNetworkEnvironment); // mock token request httpManager.AddMockHandler(new MockHttpMessageHandler { Url = string.Format(CultureInfo.InvariantCulture, "https://{0}/home/oauth2/v2.0/token", MsalTestConstants.ProductionPrefNetworkEnvironment), Method = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage() }); AuthenticationResult result = app.AcquireTokenAsync(MsalTestConstants.Scope).Result; // make sure that all cache entities are stored with "preferred_cache" environment // (it is taken from metadata in instance discovery response) ValidateCacheEntitiesEnvironment(app.UserTokenCache, MsalTestConstants.ProductionPrefCacheEnvironment); // silent request targeting at, should return at from cache for any environment alias foreach (var envAlias in MsalTestConstants.ProdEnvAliases) { result = app.AcquireTokenSilentAsync(MsalTestConstants.Scope, app.GetAccountsAsync().Result.First(), string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/", envAlias, MsalTestConstants.Utid), false).Result; Assert.IsNotNull(result); } // mock for openId config request for tenant spesific authority httpManager.AddMockHandler(new MockHttpMessageHandler { Url = string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/v2.0/.well-known/openid-configuration", MsalTestConstants.ProductionPrefNetworkEnvironment, MsalTestConstants.Utid), Method = HttpMethod.Get, ResponseMessage = MockHelpers.CreateOpenIdConfigurationResponse(MsalTestConstants.AuthorityUtidTenant) }); // silent request targeting rt should find rt in cahce for authority with any environment alias foreach (var envAlias in MsalTestConstants.ProdEnvAliases) { httpManager.AddMockHandler(new MockHttpMessageHandler() { Url = string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/oauth2/v2.0/token", MsalTestConstants.ProductionPrefNetworkEnvironment, MsalTestConstants.Utid), Method = HttpMethod.Post, PostData = new Dictionary <string, string>() { { "grant_type", "refresh_token" } }, // return not retriable status code ResponseMessage = MockHelpers.CreateInvalidGrantTokenResponseMessage() }); try { result = null; result = app.AcquireTokenSilentAsync(MsalTestConstants.ScopeForAnotherResource, app.GetAccountsAsync().Result.First(), string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/", envAlias, MsalTestConstants.Utid), false).Result; } catch (AggregateException ex) { Assert.IsNotNull(ex.InnerException); Assert.IsTrue(ex.InnerException is MsalUiRequiredException); } Assert.IsNull(result); } } }
private void SetupMocks(MockHttpManager httpManager) { httpManager.AddRegionDiscoveryMockHandler(File.ReadAllText( ResourceHelper.GetTestResourceRelativePath("local-imds-response.json"))); }
public async Task ConfidentialClientUsingCertificateTestAsync() { using (var httpManager = new MockHttpManager()) { httpManager.AddInstanceDiscoveryMockHandler(); var cert = new X509Certificate2(ResourceHelper.GetTestResourceRelativePath("valid.crtfile")); var app = CreateConfidentialClient(httpManager, cert, 3); var appCacheAccess = app.AppTokenCache.RecordAccess(); var userCacheAccess = app.UserTokenCache.RecordAccess(); var result = await app.AcquireTokenForClient(TestConstants.s_scope.ToArray()).ExecuteAsync(CancellationToken.None).ConfigureAwait(false); Assert.IsNotNull(result); Assert.IsNotNull("header.payload.signature", result.AccessToken); Assert.AreEqual(TestConstants.s_scope.AsSingleString(), result.Scopes.AsSingleString()); appCacheAccess.AssertAccessCounts(1, 1); userCacheAccess.AssertAccessCounts(0, 0); // make sure user token cache is empty Assert.AreEqual(0, app.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); Assert.AreEqual(0, app.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); // check app token cache count to be 1 Assert.AreEqual(1, app.AppTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); Assert.AreEqual(0, app.AppTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); // no RTs are returned // assert client credential Assert.IsNotNull(app.ClientCredential.CachedAssertion); Assert.AreNotEqual(0, app.ClientCredential.ValidTo); // save client assertion. string cachedAssertion = app.ClientCredential.CachedAssertion; long cacheValidTo = app.ClientCredential.ValidTo; result = await app .AcquireTokenForClient(TestConstants.s_scopeForAnotherResource.ToArray()) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); appCacheAccess.AssertAccessCounts(2, 2); userCacheAccess.AssertAccessCounts(0, 0); Assert.IsNotNull(result); Assert.AreEqual(cacheValidTo, app.ClientCredential.ValidTo); Assert.AreEqual(cachedAssertion, app.ClientCredential.CachedAssertion); // validate the send x5c forces a refresh of the cached client assertion await app .AcquireTokenForClient(TestConstants.s_scope.ToArray()) .WithSendX5C(true) .WithForceRefresh(true) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreNotEqual(cachedAssertion, app.ClientCredential.CachedAssertion); appCacheAccess.AssertAccessCounts(2, 3); userCacheAccess.AssertAccessCounts(0, 0); } }
public async Task FetchRegionFromLocalImdsCallAsync() { using (var httpManager = new MockHttpManager()) { httpManager.AddRegionDiscoveryMockHandler(TestConstants.Region); IConfidentialClientApplication app = CreateCca( httpManager, ConfidentialClientApplication.AttemptRegionDiscovery); httpManager.AddMockHandler(CreateTokenResponseHttpHandler(true)); AuthenticationResult result = await app .AcquireTokenForClient(TestConstants.s_scope) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreEqual(TestConstants.Region, result.ApiEvent.RegionUsed); Assert.AreEqual((int)RegionAutodetectionSource.Imds, result.ApiEvent.RegionAutodetectionSource); Assert.AreEqual((int)RegionOutcome.AutodetectSuccess, result.ApiEvent.RegionOutcome); // try again, result will be from cache result = await app .AcquireTokenForClient(TestConstants.s_scope) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreEqual(TestConstants.Region, result.ApiEvent.RegionUsed); Assert.AreEqual((int)RegionAutodetectionSource.Cache, result.ApiEvent.RegionAutodetectionSource); Assert.AreEqual((int)RegionOutcome.AutodetectSuccess, result.ApiEvent.RegionOutcome); Assert.IsTrue(result.AuthenticationResultMetadata.TokenSource == TokenSource.Cache); // try again, with force refresh, region should be from cache httpManager.AddMockHandler(CreateTokenResponseHttpHandler(true)); result = await app .AcquireTokenForClient(TestConstants.s_scope) .WithForceRefresh(true) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreEqual(TestConstants.Region, result.ApiEvent.RegionUsed); Assert.AreEqual((int)RegionAutodetectionSource.Cache, result.ApiEvent.RegionAutodetectionSource); Assert.AreEqual((int)RegionOutcome.AutodetectSuccess, result.ApiEvent.RegionOutcome); Assert.IsTrue(result.AuthenticationResultMetadata.TokenSource == TokenSource.IdentityProvider); // try again, create a new app, result should still be from cache IConfidentialClientApplication app2 = CreateCca( httpManager, ConfidentialClientApplication.AttemptRegionDiscovery); httpManager.AddMockHandler(CreateTokenResponseHttpHandler(true)); result = await app2 .AcquireTokenForClient(TestConstants.s_scope) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); Assert.AreEqual(TestConstants.Region, result.ApiEvent.RegionUsed); Assert.AreEqual((int)RegionAutodetectionSource.Cache, result.ApiEvent.RegionAutodetectionSource); Assert.AreEqual((int)RegionOutcome.AutodetectSuccess, result.ApiEvent.RegionOutcome); Assert.IsTrue(result.AuthenticationResultMetadata.TokenSource == TokenSource.IdentityProvider); } }
public void UnifiedCache_MsalStoresToAndReadRtFromAdalCache() { using (var httpManager = new MockHttpManager()) { httpManager.AddInstanceDiscoveryMockHandler(); var app = PublicClientApplicationBuilder.Create(MsalTestConstants.ClientId) .WithAuthority(new Uri(ClientApplicationBase.DefaultAuthority), true) .WithHttpManager(httpManager) .WithTelemetry(new TraceTelemetryConfig()) .WithUserTokenLegacyCachePersistenceForTest( new TestLegacyCachePersistance()) .BuildConcrete(); MsalMockHelpers.ConfigureMockWebUI( app.ServiceBundle.PlatformProxy, AuthorizationResult.FromUri(app.AppConfig.RedirectUri + "?code=some-code")); httpManager.AddMockHandlerForTenantEndpointDiscovery(MsalTestConstants.AuthorityCommonTenant); httpManager.AddSuccessTokenResponseMockHandlerForPost(ClientApplicationBase.DefaultAuthority); AuthenticationResult result = app.AcquireTokenInteractive(MsalTestConstants.Scope).ExecuteAsync(CancellationToken.None).Result; Assert.IsNotNull(result); // make sure Msal stored RT in Adal cache IDictionary <AdalTokenCacheKey, AdalResultWrapper> adalCacheDictionary = AdalCacheOperations.Deserialize(app.ServiceBundle.DefaultLogger, app.UserTokenCacheInternal.LegacyPersistence.LoadCache()); Assert.IsTrue(adalCacheDictionary.Count == 1); var requestContext = new RequestContext(app.ServiceBundle, Guid.NewGuid()); var accounts = app.UserTokenCacheInternal.GetAccountsAsync( MsalTestConstants.AuthorityCommonTenant, requestContext).Result; foreach (IAccount account in accounts) { app.UserTokenCacheInternal.RemoveMsalAccountWithNoLocks(account, requestContext); } httpManager.AddMockHandler( new MockHttpMessageHandler() { ExpectedMethod = HttpMethod.Post, ExpectedPostData = new Dictionary <string, string>() { { "grant_type", "refresh_token" } }, ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage( MsalTestConstants.UniqueId, MsalTestConstants.DisplayableId, MsalTestConstants.Scope.ToArray()) }); // Using RT from Adal cache for silent call AuthenticationResult result1 = app .AcquireTokenSilent(MsalTestConstants.Scope, result.Account) .WithAuthority(MsalTestConstants.AuthorityCommonTenant) .WithForceRefresh(false) .ExecuteAsync(CancellationToken.None) .Result; Assert.IsNotNull(result1); } }
public async Task WAM_AccountIds_GetMerged_Async() { // Arrange using (var httpManager = new MockHttpManager()) { var cache = new InMemoryTokenCache(); httpManager.AddInstanceDiscoveryMockHandler(); var mockBroker = Substitute.For <IBroker>(); mockBroker.IsBrokerInstalledAndInvokable(AuthorityType.Aad).Returns(true); var msalTokenResponse1 = CreateMsalTokenResponseFromWam("wam1"); var msalTokenResponse2 = CreateMsalTokenResponseFromWam("wam2"); var msalTokenResponse3 = CreateMsalTokenResponseFromWam("wam3"); // 2 apps must share the token cache, like FOCI apps, for this test to be interesting var pca1 = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithExperimentalFeatures(true) .WithTestBroker(mockBroker) .WithHttpManager(httpManager) .BuildConcrete(); var pca2 = PublicClientApplicationBuilder.Create(TestConstants.ClientId2) .WithExperimentalFeatures(true) .WithTestBroker(mockBroker) .WithHttpManager(httpManager) .BuildConcrete(); cache.Bind(pca1.UserTokenCache); cache.Bind(pca2.UserTokenCache); pca1.ServiceBundle.Config.BrokerCreatorFunc = (app, config, logger) => mockBroker; pca2.ServiceBundle.Config.BrokerCreatorFunc = (app, config, logger) => mockBroker; // Act mockBroker.AcquireTokenInteractiveAsync(null, null).ReturnsForAnyArgs(Task.FromResult(msalTokenResponse1)); await pca1.AcquireTokenInteractive(TestConstants.s_scope).ExecuteAsync().ConfigureAwait(false); // this should override wam1 id mockBroker.AcquireTokenInteractiveAsync(null, null).ReturnsForAnyArgs(Task.FromResult(msalTokenResponse2)); await pca1.AcquireTokenInteractive(TestConstants.s_scope).ExecuteAsync().ConfigureAwait(false); mockBroker.AcquireTokenInteractiveAsync(null, null).ReturnsForAnyArgs(Task.FromResult(msalTokenResponse3)); await pca2.AcquireTokenInteractive(TestConstants.s_scope).ExecuteAsync().ConfigureAwait(false); var accounts1 = await pca1.GetAccountsAsync().ConfigureAwait(false); var accounts2 = await pca2.GetAccountsAsync().ConfigureAwait(false); // Assert #if SUPPORTS_BROKER var wamAccountIds = (accounts1.Single() as Account).WamAccountIds; Assert.AreEqual(2, wamAccountIds.Count); Assert.AreEqual("wam2", wamAccountIds[TestConstants.ClientId]); Assert.AreEqual("wam3", wamAccountIds[TestConstants.ClientId2]); CoreAssert.AssertDictionariesAreEqual(wamAccountIds, (accounts2.Single() as Account).WamAccountIds, StringComparer.Ordinal); #else Assert.IsTrue(accounts1.All(a => (a as IAccountInternal).WamAccountIds == null)); Assert.IsTrue(accounts2.All(a => (a as IAccountInternal).WamAccountIds == null)); #endif } }
[WorkItem(695)] // Fix for https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/695 public void AcquireTokenSilentForceRefreshFalseMultipleTenantsTest() { using (var httpManager = new MockHttpManager()) { PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId) .WithAuthority(new Uri(ClientApplicationBase.DefaultAuthority), true) .WithHttpManager(httpManager) .WithTelemetry(new TraceTelemetryConfig()) .BuildConcrete(); // PopulateCache() creates two access tokens var tokenCacheHelper = new TokenCacheHelper(); tokenCacheHelper.PopulateCache(app.UserTokenCacheInternal.Accessor); Task <AuthenticationResult> task = app .AcquireTokenSilent( TestConstants.s_scope.ToArray(), new Account(TestConstants.s_userIdentifier, TestConstants.DisplayableId, null)) .WithAuthority(TestConstants.AuthorityCommonTenant) .WithForceRefresh(false) .ExecuteAsync(CancellationToken.None); AuthenticationResult result = task.Result; Assert.IsNotNull(result); Assert.AreEqual(TestConstants.DisplayableId, result.Account.Username); Assert.AreEqual(TestConstants.s_scope.ToArray().AsSingleString(), result.Scopes.AsSingleString()); Assert.AreEqual(0, httpManager.QueueSize); Assert.AreEqual(2, app.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); Assert.AreEqual(1, app.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); httpManager.AddInstanceDiscoveryMockHandler(); httpManager.AddMockHandlerForTenantEndpointDiscovery(TestConstants.AuthorityGuidTenant2); httpManager.AddMockHandler( new MockHttpMessageHandler() { ExpectedMethod = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage( TestConstants.UniqueId, TestConstants.DisplayableId, TestConstants.s_scope.ToArray()) }); // Same user, scopes, clientId, but different authority // Should result in new AccessToken, but same refresh token Task <AuthenticationResult> task2 = app .AcquireTokenSilent( TestConstants.s_scope.ToArray(), new Account(TestConstants.s_userIdentifier, TestConstants.DisplayableId, null)) .WithAuthority(TestConstants.AuthorityGuidTenant2) .WithForceRefresh(false) .ExecuteAsync(CancellationToken.None); AuthenticationResult result2 = task2.Result; Assert.IsNotNull(result2); Assert.AreEqual(TestConstants.DisplayableId, result2.Account.Username); Assert.AreEqual(TestConstants.s_scope.ToArray().AsSingleString(), result2.Scopes.AsSingleString()); Assert.AreEqual(3, app.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); Assert.AreEqual(1, app.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); httpManager.AddMockHandlerForTenantEndpointDiscovery(TestConstants.AuthorityGuidTenant); httpManager.AddMockHandler( new MockHttpMessageHandler() { ExpectedMethod = HttpMethod.Post, ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage( TestConstants.UniqueId, TestConstants.DisplayableId, TestConstants.s_scope.ToArray()) }); // Same user, scopes, clientId, but different authority // Should result in new AccessToken, but same refresh token Task <AuthenticationResult> task3 = app .AcquireTokenSilent( TestConstants.s_scope.ToArray(), new Account(TestConstants.s_userIdentifier, TestConstants.DisplayableId, null)) .WithAuthority(TestConstants.AuthorityGuidTenant) .WithForceRefresh(false) .ExecuteAsync(CancellationToken.None); AuthenticationResult result3 = task3.Result; Assert.IsNotNull(result3); Assert.AreEqual(TestConstants.DisplayableId, result3.Account.Username); Assert.AreEqual(TestConstants.s_scope.ToArray().AsSingleString(), result3.Scopes.AsSingleString()); Assert.AreEqual(4, app.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); Assert.AreEqual(1, app.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); } }
private static void MockInstanceDiscoveryAndOpenIdRequest(MockHttpManager mockHttpManager) { mockHttpManager.AddInstanceDiscoveryMockHandler(); }
public void UnifiedCache_RemoveAccountIsApplicationSpecific() { byte[] data = null; using (var httpManager = new MockHttpManager()) { // login to app var app = PublicClientApplicationBuilder.Create(MsalTestConstants.ClientId) .WithAuthority(new Uri(ClientApplicationBase.DefaultAuthority), true) .WithHttpManager(httpManager) .WithTelemetry(new TraceTelemetryConfig()) .BuildConcrete(); app.UserTokenCache.SetBeforeAccess((TokenCacheNotificationArgs args) => { args.TokenCache.DeserializeMsalV3(data); }); app.UserTokenCache.SetAfterAccess((TokenCacheNotificationArgs args) => { data = args.TokenCache.SerializeMsalV3(); }); httpManager.AddInstanceDiscoveryMockHandler(); MsalMockHelpers.ConfigureMockWebUI( app.ServiceBundle.PlatformProxy, AuthorizationResult.FromUri(app.AppConfig.RedirectUri + "?code=some-code")); httpManager.AddMockHandlerForTenantEndpointDiscovery(MsalTestConstants.AuthorityCommonTenant); httpManager.AddSuccessTokenResponseMockHandlerForPost(ClientApplicationBase.DefaultAuthority); AuthenticationResult result = app .AcquireTokenInteractive(MsalTestConstants.Scope) .ExecuteAsync(CancellationToken.None) .Result; Assert.IsNotNull(result); Assert.AreEqual(1, app.UserTokenCacheInternal.Accessor.GetAllAccounts().Count()); Assert.AreEqual(1, app.GetAccountsAsync().Result.Count()); // login to app1 with same credentials var app1 = PublicClientApplicationBuilder.Create(MsalTestConstants.ClientId2) .WithHttpManager(httpManager) .WithTelemetry(new TraceTelemetryConfig()) .WithAuthority( new Uri(ClientApplicationBase.DefaultAuthority), true).BuildConcrete(); MsalMockHelpers.ConfigureMockWebUI( app1.ServiceBundle.PlatformProxy, AuthorizationResult.FromUri(app.AppConfig.RedirectUri + "?code=some-code")); app1.UserTokenCache.SetBeforeAccess((TokenCacheNotificationArgs args) => { args.TokenCache.DeserializeMsalV3(data); }); app1.UserTokenCache.SetAfterAccess((TokenCacheNotificationArgs args) => { data = args.TokenCache.SerializeMsalV3(); }); httpManager.AddSuccessTokenResponseMockHandlerForPost(ClientApplicationBase.DefaultAuthority); result = app1 .AcquireTokenInteractive(MsalTestConstants.Scope) .ExecuteAsync(CancellationToken.None) .Result; Assert.IsNotNull(result); // make sure that only one account cache entity was created Assert.AreEqual(1, app1.GetAccountsAsync().Result.Count()); Assert.AreEqual(2, app1.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count()); Assert.AreEqual(2, app1.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count()); Assert.AreEqual(2, app1.UserTokenCacheInternal.Accessor.GetAllIdTokens().Count()); Assert.AreEqual(1, app1.UserTokenCacheInternal.Accessor.GetAllAccounts().Count()); // remove account from app app.RemoveAsync(app.GetAccountsAsync().Result.First()).Wait(); // make sure account removed from app Assert.AreEqual(0, app.GetAccountsAsync().Result.Count()); // make sure account Not removed from app1 Assert.AreEqual(1, app1.GetAccountsAsync().Result.Count()); } }
// regression: https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/2686 public async Task OtherCloudWithAuthorityValidationAsync() { const string imdsError = "IMDS call failed with exception"; const string autoDiscoveryError = "Auto-discovery failed in the past. Not trying again. IMDS call failed"; using (var httpManager = new MockHttpManager()) { httpManager.AddRegionDiscoveryMockHandlerNotFound(); var discoveryHandler = MockHelpers.CreateInstanceDiscoveryMockHandler( "https://login.microsoftonline.com/common/discovery/instance", TestConstants.DiscoveryJsonResponse); var tokenHttpCallHandler = new MockHttpMessageHandler() { ExpectedUrl = "https://eastus.login.windows-ppe.org/17b189bc-2b81-4ec5-aa51-3e628cbc931b/oauth2/v2.0/token", ExpectedMethod = HttpMethod.Post, ResponseMessage = CreateResponse(true) }; httpManager.AddMockHandler(discoveryHandler); httpManager.AddMockHandler(tokenHttpCallHandler); var app = ConfidentialClientApplicationBuilder .Create(TestConstants.ClientId) .WithAuthority("https://" + TestConstants.PpeOrgEnvironment + "/common", true) //login.windows-ppe.org is not known to MSAL .WithHttpManager(httpManager) .WithAzureRegion(EastUsRegion) .WithClientSecret(TestConstants.ClientSecret) .Build(); #pragma warning disable CS0618 // Type or member is obsolete AuthenticationResult result = await app .AcquireTokenForClient(TestConstants.s_scope) .WithAuthority("https://" + TestConstants.PpeOrgEnvironment + "/17b189bc-2b81-4ec5-aa51-3e628cbc931b") .ExecuteAsync() .ConfigureAwait(false); Assert.AreEqual(EastUsRegion, result.ApiEvent.RegionUsed); Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource); Assert.AreEqual( "https://login.microsoftonline.com/common/discovery/instance?api-version=1.1&authorization_endpoint=https%3A%2F%2Flogin.windows-ppe.org%2F17b189bc-2b81-4ec5-aa51-3e628cbc931b%2Foauth2%2Fv2.0%2Fauthorize", discoveryHandler.ActualRequestMessage.RequestUri.AbsoluteUri, "Authority validation is made on https://login.microsoftonline.com/ and it validates the auth_endpoint of the non-regional authority"); Assert.AreEqual(EastUsRegion, result.AuthenticationResultMetadata.RegionDetails.RegionUsed); Assert.AreEqual(RegionOutcome.UserProvidedAutodetectionFailed, result.AuthenticationResultMetadata.RegionDetails.RegionOutcome); Assert.IsTrue(result.AuthenticationResultMetadata.RegionDetails.AutoDetectionError.Contains(imdsError)); result = await app .AcquireTokenForClient(TestConstants.s_scope) .WithAuthority("https://" + TestConstants.PpeOrgEnvironment + "/17b189bc-2b81-4ec5-aa51-3e628cbc931b") .ExecuteAsync() .ConfigureAwait(false); #pragma warning restore CS0618 // Type or member is obsolete Assert.AreEqual(EastUsRegion, result.ApiEvent.RegionUsed); Assert.AreEqual(TokenSource.Cache, result.AuthenticationResultMetadata.TokenSource); Assert.AreEqual(EastUsRegion, result.AuthenticationResultMetadata.RegionDetails.RegionUsed); Assert.AreEqual(RegionOutcome.UserProvidedAutodetectionFailed, result.AuthenticationResultMetadata.RegionDetails.RegionOutcome); Assert.IsTrue(result.AuthenticationResultMetadata.RegionDetails.AutoDetectionError.Contains(autoDiscoveryError)); } }