Beispiel #1
0
        public async Task TelemetryAcceptanceTestAsync()
        {
            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();

                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 refresh_token flow");
                result = await RunAcquireTokenSilentAsync(AcquireTokenSilentOutcome.SuccessViaRefreshGrant).ConfigureAwait(false);

                AssertCurrentTelemetry(result.HttpRequest, ApiIds.AcquireTokenSilent, CacheRefreshReason.NoCachedAccessToken);
                AssertPreviousTelemetry(result.HttpRequest, expectedSilentCount: 1);

                Trace.WriteLine("Step 4. Acquire Token Silent with force_refresh = true and failure = invalid_grant");
                result = await RunAcquireTokenSilentAsync(AcquireTokenSilentOutcome.FailInvalidGrant, forceRefresh : true).ConfigureAwait(false);

                AssertCurrentTelemetry(result.HttpRequest, ApiIds.AcquireTokenSilent, CacheRefreshReason.ForceRefreshOrClaims);
                AssertPreviousTelemetry(result.HttpRequest, expectedSilentCount: 0);

                // invalid grant error puts MSAL in a throttled state - simulate some time passing for this
                _harness.ServiceBundle.ThrottlingManager.SimulateTimePassing(
                    UiRequiredProvider.s_uiRequiredExpiration.Add(TimeSpan.FromSeconds(1)));

                Guid step4Correlationid = result.Correlationid;
                Trace.WriteLine("Step 5. Acquire Token Silent with force_refresh = true and failure = interaction_required");
                result = await RunAcquireTokenSilentAsync(AcquireTokenSilentOutcome.FailInteractionRequired, forceRefresh : true).ConfigureAwait(false);

                AssertCurrentTelemetry(result.HttpRequest, ApiIds.AcquireTokenSilent, CacheRefreshReason.ForceRefreshOrClaims);
                AssertPreviousTelemetry(
                    result.HttpRequest,
                    expectedSilentCount: 0,
                    expectedFailedApiIds: new[] { ApiIds.AcquireTokenSilent }, // from step 4
                    expectedCorrelationIds: new[] { step4Correlationid },
                    expectedErrors: new[] { "invalid_grant" });
                Guid step5CorrelationId = result.Correlationid;

                Trace.WriteLine("Step 6. Acquire Token Interactive -  some /authorization error  -> token endpoint not hit");
                result = await RunAcquireTokenInteractiveAsync(AcquireTokenInteractiveOutcome.AuthorizationError).ConfigureAwait(false);

                Assert.IsNull(result.HttpRequest, "No calls are made to the token endpoint");
                Guid step6CorrelationId = result.Correlationid;

                Trace.WriteLine("Step 7. Acquire Token Interactive -> HTTP 5xx error (i.e. AAD is down)");
                result = await RunAcquireTokenInteractiveAsync(AcquireTokenInteractiveOutcome.AADUnavailableError).ConfigureAwait(false);

                Guid step7CorrelationId = result.Correlationid;

                // we can assert telemetry here, as it will be sent to AAD. However, AAD is down, so it will not record it.
                AssertCurrentTelemetry(result.HttpRequest, ApiIds.AcquireTokenInteractive, CacheRefreshReason.NotApplicable);
                AssertPreviousTelemetry(
                    result.HttpRequest,
                    expectedSilentCount: 0,
                    expectedFailedApiIds: new[] { ApiIds.AcquireTokenSilent, ApiIds.AcquireTokenInteractive },
                    expectedCorrelationIds: new[] { step5CorrelationId, step6CorrelationId },
                    expectedErrors: new[] { "interaction_required", "user_cancelled" });

                // the 5xx error puts MSAL in a throttling state, so "wait" until this clears
                _harness.ServiceBundle.ThrottlingManager.SimulateTimePassing(
                    HttpStatusProvider.s_throttleDuration.Add(TimeSpan.FromSeconds(1)));

                Trace.WriteLine("Step 8. Acquire Token Interactive -> Success");
                result = await RunAcquireTokenInteractiveAsync(AcquireTokenInteractiveOutcome.Success).ConfigureAwait(false);

                AssertCurrentTelemetry(result.HttpRequest, ApiIds.AcquireTokenInteractive, CacheRefreshReason.NotApplicable);
                AssertPreviousTelemetry(
                    result.HttpRequest,
                    expectedSilentCount: 0,
                    expectedFailedApiIds: new[] { ApiIds.AcquireTokenSilent, ApiIds.AcquireTokenInteractive, ApiIds.AcquireTokenInteractive },
                    expectedCorrelationIds: new[] { step5CorrelationId, step6CorrelationId, step7CorrelationId },
                    expectedErrors: new[] { "interaction_required", "user_cancelled", "service_not_available" });

                Trace.WriteLine("Step 9. Acquire Token Silent with force-refresh false -> successful");
                result = await RunAcquireTokenSilentAsync(AcquireTokenSilentOutcome.SuccessViaRefreshGrant, false).ConfigureAwait(false);

                AssertCurrentTelemetry(result.HttpRequest, ApiIds.AcquireTokenSilent, CacheRefreshReason.NoCachedAccessToken);
                AssertPreviousTelemetry(result.HttpRequest, expectedSilentCount: 0);
            }
        }
Beispiel #2
0
        public void TestGetAccounts()
        {
            var tokenCacheHelper = new TokenCacheHelper();

            using (var httpManager = new MockHttpManager())
            {
                PublicClientApplication app = PublicClientApplicationBuilder.Create(TestConstants.ClientId)
                                              .WithHttpManager(httpManager)
                                              .WithTelemetry(new TraceTelemetryConfig())
                                              .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(
                    TestConstants.ProductionPrefCacheEnvironment,
                    TestConstants.ClientId,
                    TestConstants.s_scope.AsSingleString(),
                    TestConstants.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(
                    TestConstants.ProductionPrefCacheEnvironment,
                    TestConstants.ClientId,
                    "someRT",
                    MockHelpers.CreateClientInfo("uId1", "uTId1"));

                app.UserTokenCacheInternal.Accessor.SaveRefreshToken(rtItem);

                MsalIdTokenCacheItem idTokenCacheItem = new MsalIdTokenCacheItem(
                    TestConstants.ProductionPrefCacheEnvironment,
                    TestConstants.ClientId,
                    MockHelpers.CreateIdToken(TestConstants.UniqueId, TestConstants.DisplayableId),
                    MockHelpers.CreateClientInfo("uId1", "uTId1"),
                    "uTId1");

                app.UserTokenCacheInternal.Accessor.SaveIdToken(idTokenCacheItem);

                MsalAccountCacheItem accountCacheItem = new MsalAccountCacheItem(
                    TestConstants.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(
                    TestConstants.SovereignNetworkEnvironment,
                    TestConstants.ClientId,
                    "someRT",
                    MockHelpers.CreateClientInfo(TestConstants.Uid + "more1", TestConstants.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());
            }
        }
Beispiel #3
0
        static async Task Main(string[] args)
        {
            // Create the MSAL client object (public or confidential, depending on your context)
            publicClient = PublicClientApplicationBuilder
                           .Create(clientId)
                           .WithAuthority(authority)
                           .WithRedirectUri("http://localhost")
                           .Build();

            // Create an authentication provider by passing in a client application and graph scopes.
            InteractiveAuthenticationProvider authProvider = new InteractiveAuthenticationProvider(publicClient, graphScopes);

            // Create a new instance of GraphServiceClient with the authentication provider.
            GraphServiceClient graphClient = new GraphServiceClient(authProvider);

            // *****************************************
            // Requesting a single object like "me"
            // *****************************************

            var me = await graphClient.Me.Request().GetAsync();

            Console.WriteLine(me.DisplayName);

            // *****************************************
            // Querying list of data with with Top/Skip
            // *****************************************

            int counter = 0;
            var users   = await graphClient.Users.Request().Select("Id,DisplayName,UserPrincipalName").OrderBy("DisplayName").Top(20).GetAsync();

            Console.WriteLine(users.Count);

            foreach (var user in users)
            {
                counter++;
                Console.WriteLine($"{counter:000} | {user.Id} => {user.DisplayName} <{user.UserPrincipalName}>");
            }

            // *************************************
            // Querying list of data with paging
            // *************************************

            counter = 0;
            var messages = await graphClient.Me.Messages.Request().Select("Id,Subject").OrderBy("Subject").GetAsync();

            var messagesIterator = PageIterator <Message> .CreatePageIterator(graphClient, messages, (message) => {
                counter++;
                Console.WriteLine($"{counter:000} | {message.Id} => {message.Subject}");
                return(counter < 2000); // Stop after 2000 messages
            });

            await messagesIterator.IterateAsync();

            // **************************
            // Working with batching
            // **************************

            // Define a couple of request
            var userRequest     = graphClient.Me.Request();
            var messagesRequest = graphClient.Me.Messages.Request().Select("Id,Subject").OrderBy("Subject").Top(20);

            // Build a batch
            var batchRequestContent = new BatchRequestContent();

            // Using AddBatchRequestStep adds each request as a step
            // with no specified order of execution
            var userRequestId     = batchRequestContent.AddBatchRequestStep(userRequest);
            var messagesRequestId = batchRequestContent.AddBatchRequestStep(messagesRequest);

            // Process the actual batch request
            var returnedResponse = await graphClient.Batch.Request().PostAsync(batchRequestContent);

            // Try to get the responses
            try
            {
                var user = await returnedResponse
                           .GetResponseByIdAsync <User>(userRequestId);

                Console.WriteLine($"Hello {user.DisplayName}!");
            }
            catch (ServiceException ex)
            {
                Console.WriteLine($"Get user failed: {ex.Error.Message}");
            }

            try
            {
                var messagesViaBatch = await returnedResponse
                                       .GetResponseByIdAsync <UserMessagesCollectionResponse>(messagesRequestId);

                counter = 0;
                foreach (var message in messagesViaBatch.Value)
                {
                    counter++;
                    Console.WriteLine($"{counter:000} | {message.Id} => {message.Subject}");
                }
            }
            catch (ServiceException ex)
            {
                Console.WriteLine($"Get messages failed: {ex.Error.Message}");
            }
        }
Beispiel #4
0
 internal TokenCache(TokenCachePersistenceOptions options, MsalCacheHelperWrapper cacheHelperWrapper, Func <IPublicClientApplication> publicApplicationFactory = null)
 {
     _cacheHelperWrapper             = cacheHelperWrapper ?? new MsalCacheHelperWrapper();
     _publicClientApplicationFactory = publicApplicationFactory ?? new Func <IPublicClientApplication>(() => PublicClientApplicationBuilder.Create(Guid.NewGuid().ToString()).Build());
     if (options is UnsafeTokenCacheOptions inMemoryOptions)
     {
         TokenCacheUpdatedAsync       = inMemoryOptions.TokenCacheUpdatedAsync;
         RefreshCacheFromOptionsAsync = inMemoryOptions.RefreshCacheAsync;
         _lastUpdated    = DateTimeOffset.UtcNow;
         _cacheAccessMap = new ConditionalWeakTable <object, CacheTimestamp>();
     }
     else
     {
         _allowUnencryptedStorage = options?.UnsafeAllowUnencryptedStorage ?? false;
         _name          = options?.Name ?? Constants.DefaultMsalTokenCacheName;
         _persistToDisk = true;
     }
 }
Beispiel #5
0
        static async Task Main(string[] args)
        {
            var publicClientApp = PublicClientApplicationBuilder.Create(ClientId)
                                  .WithRedirectUri("http://localhost")
                                  .WithAuthority(AzureCloudInstance.AzurePublic, Tenant)
                                  .Build();

            var repo = new GraphGroupRepository(new InteractiveAuthenticationProvider(publicClientApp), new Logger());

            bool compareGroups = args.Length == 2;
            var  users         = new List <HashSet <AzureADUser> >();
            var  cycles        = new List <SecurityGroupCycle>();

            foreach (var groupToTraverse in args.Select(x => Guid.Parse(x)))
            {
                Console.WriteLine("Checking group: " + groupToTraverse);

                if (await repo.GroupExists(groupToTraverse) == false)
                {
                    Console.WriteLine($"{groupToTraverse} doesn't exist. Skipping.");
                    continue;
                }

                var crawler       = new SGCrawler(repo);
                var crawlerUsers  = new ConcurrentDictionary <AzureADUser, byte>();
                var crawlerGroups = new ConcurrentBag <AzureADGroup>();
                var crawlerCycles = new ConcurrentBag <SecurityGroupCycle>();

                crawler.FoundUserAction       = (user) => { crawlerUsers.TryAdd(user, 0); };
                crawler.FoundGroupAction      = (group) => { crawlerGroups.Add(group); };
                crawler.FoundGroupCycleAction = (cycle) => { crawlerCycles.Add(cycle); };

                var stopwatch = Stopwatch.StartNew();
                await crawler.CrawlGroup(new AzureADGroup { ObjectId = groupToTraverse });

                stopwatch.Stop();
                Console.WriteLine($"Found {crawlerUsers.Count} total ({crawlerUsers.Keys.Distinct().Count()} distinct) users in {crawlerGroups.Count} total ({crawlerGroups.Distinct().Count()} distinct) nested groups in {stopwatch.ElapsedMilliseconds} ms.");

                Console.WriteLine($"Found {crawlerCycles.Count} cycles.");
                if (crawlerCycles.Any())
                {
                    cycles.AddRange(crawlerCycles);
                    foreach (var cycle in crawlerCycles)
                    {
                        Console.WriteLine(cycle);
                    }
                }


                if (compareGroups)
                {
                    users.Add(new HashSet <AzureADUser>(crawlerUsers.Keys));
                }
            }

            if (compareGroups && users.Count == 2)
            {
                Console.WriteLine($"The following users are in {args[0]} but not {args[1]}:");
                Console.WriteLine(string.Join(Environment.NewLine, users[0].Except(users[1])));
                Console.WriteLine($"The following users are in {args[1]} but not {args[0]}:");
                Console.WriteLine(string.Join(Environment.NewLine, users[1].Except(users[0])));
            }

            if (cycles.Any())
            {
                Console.WriteLine($"Found {cycles.Count} cycles across all groups checked.");
                foreach (var cycle in cycles)
                {
                    Console.WriteLine(cycle);
                }
            }
        }
Beispiel #6
0
        public static async Task <string> GetLabAccessTokenAsync(string authority, string[] scopes, LabAccessAuthenticationType authType, string clientId, string certThumbprint, string clientSecret)
        {
            AuthenticationResult           authResult;
            IConfidentialClientApplication confidentialApp;
            X509Certificate2 cert;

            switch (authType)
            {
            case LabAccessAuthenticationType.ClientCertificate:
                var clientIdForCertAuth  = String.IsNullOrEmpty(clientId) ? LabAccessConfidentialClientId : clientId;
                var certThumbprintForLab = String.IsNullOrEmpty(clientId) ? LabAccessThumbPrint : certThumbprint;

                cert = CertificateHelper.FindCertificateByThumbprint(certThumbprintForLab);
                if (cert == null)
                {
                    throw new InvalidOperationException(
                              "Test setup error - cannot find a certificate in the My store for KeyVault. This is available for Microsoft employees only.");
                }

                confidentialApp = ConfidentialClientApplicationBuilder
                                  .Create(clientIdForCertAuth)
                                  .WithAuthority(new Uri(authority), true)
                                  .WithCertificate(cert)
                                  .Build();

                s_staticCache.Bind(confidentialApp.AppTokenCache);

                authResult = await confidentialApp
                             .AcquireTokenForClient(scopes)
                             .ExecuteAsync(CancellationToken.None)
                             .ConfigureAwait(false);

                break;

            case LabAccessAuthenticationType.ClientSecret:
                var clientIdForSecretAuth = String.IsNullOrEmpty(clientId) ? LabAccessConfidentialClientId : clientId;
                var clientSecretForLab    = String.IsNullOrEmpty(clientId) ? s_secret : clientSecret;

                confidentialApp = ConfidentialClientApplicationBuilder
                                  .Create(clientIdForSecretAuth)
                                  .WithAuthority(new Uri(authority), true)
                                  .WithClientSecret(clientSecretForLab)
                                  .Build();
                s_staticCache.Bind(confidentialApp.AppTokenCache);

                authResult = await confidentialApp
                             .AcquireTokenForClient(scopes)
                             .ExecuteAsync(CancellationToken.None)
                             .ConfigureAwait(false);

                break;

            case LabAccessAuthenticationType.UserCredential:
                var clientIdForPublicClientAuth = String.IsNullOrEmpty(clientId) ? LabAccessPublicClientId : clientId;
                var publicApp = PublicClientApplicationBuilder
                                .Create(clientIdForPublicClientAuth)
                                .WithAuthority(new Uri(authority), true)
                                .Build();
                s_staticCache.Bind(publicApp.UserTokenCache);

                authResult = await publicApp
                             .AcquireTokenByIntegratedWindowsAuth(scopes)
                             .ExecuteAsync(CancellationToken.None)
                             .ConfigureAwait(false);

                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            return(authResult?.AccessToken);
        }
Beispiel #7
0
        public void UnifiedCache_RemoveAccountIsApplicationSpecific()
        {
            byte[] data = null;

            using (var httpManager = new MockHttpManager())
            {
                // login to app
                var app = PublicClientApplicationBuilder.Create(TestConstants.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();

                app.ServiceBundle.ConfigureMockWebUI(
                    AuthorizationResult.FromUri(app.AppConfig.RedirectUri + "?code=some-code"));

                httpManager.AddSuccessTokenResponseMockHandlerForPost(ClientApplicationBase.DefaultAuthority);

                AuthenticationResult result = app
                                              .AcquireTokenInteractive(TestConstants.s_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(TestConstants.ClientId2)
                           .WithHttpManager(httpManager)
                           .WithTelemetry(new TraceTelemetryConfig())
                           .WithAuthority(
                    new Uri(ClientApplicationBase.DefaultAuthority),
                    true).BuildConcrete();

                app1.ServiceBundle.ConfigureMockWebUI(
                    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(TestConstants.s_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());
            }
        }
Beispiel #8
0
 public OneDrive()
 {
     PCA = PublicClientApplicationBuilder.Create(ClientID)
           .WithRedirectUri($"msal{ClientID}://auth")
           .Build();
 }
        [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());
            }
        }
            /// <inheritdoc />
            protected override async Task <IEnumerable <CacheExecutorAccountResult> > InternalExecuteAsync(TestInputData testInputData)
            {
                string resource = TestInputData.MsGraph;

                string[] scopes = new[]
                {
                    resource + "/user.read"
                };

                var results = new List <CacheExecutorAccountResult>();

                foreach (var labUserData in testInputData.LabUserDatas)
                {
                    var app = PublicClientApplicationBuilder
                              .Create(labUserData.ClientId)
                              .WithAuthority(new Uri(labUserData.Authority), true)
                              .WithLogging((LogLevel level, string message, bool containsPii) =>
                    {
                        Console.WriteLine("{0}: {1}", level, message);
                    })
                              .Build();

                    FileBasedTokenCacheHelper.ConfigureUserCache(
                        testInputData.StorageType,
                        app.UserTokenCache,
                        CommonCacheTestUtils.AdalV3CacheFilePath,
                        CommonCacheTestUtils.MsalV2CacheFilePath,
                        CommonCacheTestUtils.MsalV3CacheFilePath);

                    IEnumerable <IAccount> accounts = await app.GetAccountsAsync().ConfigureAwait(false);

                    IAccount accountToReference = accounts.FirstOrDefault(x => x.Username.Equals(labUserData.Upn, StringComparison.OrdinalIgnoreCase));

                    try
                    {
                        var result = await app
                                     .AcquireTokenSilent(scopes, accountToReference)
                                     .WithAuthority(app.Authority)
                                     .WithForceRefresh(false)
                                     .ExecuteAsync(CancellationToken.None)
                                     .ConfigureAwait(false);

                        Console.WriteLine($"got token for '{result.Account.Username}' from the cache");

                        results.Add(new CacheExecutorAccountResult(labUserData.Upn, result.Account.Username, true));
                    }
                    catch (MsalUiRequiredException)
                    {
                        var result = await app
                                     .AcquireTokenByUsernamePassword(scopes, labUserData.Upn, labUserData.Password.ToSecureString())
                                     .ExecuteAsync(CancellationToken.None)
                                     .ConfigureAwait(false);

                        if (string.IsNullOrWhiteSpace(result.AccessToken))
                        {
                            results.Add(new CacheExecutorAccountResult(labUserData.Upn, string.Empty, false));
                        }
                        else
                        {
                            Console.WriteLine($"got token for '{result.Account.Username}' without the cache");
                            results.Add(new CacheExecutorAccountResult(labUserData.Upn, result.Account.Username, false));
                        }
                    }
                }

                return(results);
            }
Beispiel #11
0
        public async Task <IAzureWorkspace?> GetAuthenticatedWorkspaceAsync(
            IChannel channel,
            ILogger?logger,
            string resourceGroupName,
            string workspaceName,
            bool refreshCredentials)
        {
            if (Type == AzureEnvironmentType.Mock)
            {
                channel.Stdout("AZURE_QUANTUM_ENV set to Mock. Using mock Azure workspace rather than connecting to the real service.");
                return(new MockAzureWorkspace(workspaceName));
            }

            // Find the token cache folder
            var cacheDirectoryEnvVarName = "AZURE_QUANTUM_TOKEN_CACHE";
            var cacheDirectory           = System.Environment.GetEnvironmentVariable(cacheDirectoryEnvVarName);

            if (string.IsNullOrEmpty(cacheDirectory))
            {
                cacheDirectory = Path.Join(System.Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile), ".azure-quantum");
            }

            // Register the token cache for serialization
            var cacheFileName             = "iqsharp.bin";
            var storageCreationProperties = new StorageCreationPropertiesBuilder(cacheFileName, cacheDirectory, ClientId)
                                            .WithMacKeyChain(
                serviceName: "Microsoft.Quantum.IQSharp",
                accountName: "MSALCache")
                                            .WithLinuxKeyring(
                schemaName: "com.microsoft.quantum.iqsharp",
                collection: "default",
                secretLabel: "Credentials used by Microsoft IQ# kernel",
                attribute1: new KeyValuePair <string, string>("Version", typeof(AzureClient).Assembly.GetName().Version.ToString()),
                attribute2: new KeyValuePair <string, string>("ProductGroup", "QDK"))
                                            .Build();

            MsalCacheHelper?cacheHelper;

            try
            {
                cacheHelper = await MsalCacheHelper.CreateAsync(storageCreationProperties);

                cacheHelper.VerifyPersistence();
            }
            catch (MsalCachePersistenceException e)
            {
                // Will occur on Linux if encryption is unavailable. Fallback to unencrypted cache on Linux, as documented here:
                // https://github.com/AzureAD/microsoft-authentication-extensions-for-dotnet/blob/master/docs/keyring_fallback_proposal.md
                var unencryptedCacheFileName = "iqsharp-unencrypted.bin";
                logger?.LogWarning(e,
                                   "Encrypted credential cache is unavailable. Cache will be stored in plaintext at {Path}. Error: {Message}",
                                   Path.Combine(cacheDirectory, unencryptedCacheFileName),
                                   e.Message);

                storageCreationProperties = new StorageCreationPropertiesBuilder(unencryptedCacheFileName, cacheDirectory, ClientId)
                                            .WithMacKeyChain(
                    serviceName: "Microsoft.Quantum.IQSharp",
                    accountName: "MSALCache")
                                            .WithLinuxUnprotectedFile()
                                            .Build();

                cacheHelper = await MsalCacheHelper.CreateAsync(storageCreationProperties);

                cacheHelper.VerifyPersistence();
            }

            var msalApp = PublicClientApplicationBuilder.Create(ClientId).WithAuthority(Authority).Build();

            cacheHelper.RegisterCache(msalApp.UserTokenCache);

            // Perform the authentication
            bool shouldShowLoginPrompt = refreshCredentials;
            AuthenticationResult?authenticationResult = null;

            if (!shouldShowLoginPrompt)
            {
                try
                {
                    var accounts = await msalApp.GetAccountsAsync();

                    authenticationResult = await msalApp.AcquireTokenSilent(
                        Scopes, accounts.FirstOrDefault()).WithAuthority(msalApp.Authority).ExecuteAsync();
                }
                catch (MsalUiRequiredException)
                {
                    shouldShowLoginPrompt = true;
                }
            }

            if (shouldShowLoginPrompt)
            {
                authenticationResult = await msalApp.AcquireTokenWithDeviceCode(
                    Scopes,
                    deviceCodeResult =>
                {
                    channel.Stdout(deviceCodeResult.Message);
                    return(Task.FromResult(0));
                }).WithAuthority(msalApp.Authority).ExecuteAsync();
            }

            if (authenticationResult == null)
            {
                return(null);
            }

            // Construct and return the AzureWorkspace object
            var credentials        = new Rest.TokenCredentials(authenticationResult.AccessToken);
            var azureQuantumClient = new QuantumClient(credentials)
            {
                SubscriptionId    = SubscriptionId,
                ResourceGroupName = resourceGroupName,
                WorkspaceName     = workspaceName,
                BaseUri           = BaseUri,
            };
            var azureQuantumWorkspace = new Azure.Quantum.Workspace(
                azureQuantumClient.SubscriptionId,
                azureQuantumClient.ResourceGroupName,
                azureQuantumClient.WorkspaceName,
                authenticationResult?.AccessToken,
                BaseUri);

            return(new AzureWorkspace(azureQuantumClient, azureQuantumWorkspace));
        }
Beispiel #12
0
        public async Task AcquireTokenSilent_ValidATs_ParallelRequests_Async()
        {
            // Arrange
            const int NumberOfRequests = 10;

            using (MockHttpAndServiceBundle harness = CreateTestHarness())
            {
                PublicClientApplication pca = PublicClientApplicationBuilder
                                              .Create(TestConstants.ClientId)
                                              .WithHttpManager(harness.HttpManager)
                                              .BuildConcrete();

                ConfigureCacheSerialization(pca);

                var actualUsers = new List <string>();
                for (int i = 1; i <= NumberOfRequests; i++)
                {
                    var user = GetUpn(i);
                    _tokenCacheHelper.PopulateCache(pca.UserTokenCacheInternal.Accessor, GetUid(i), "utid", displayableId: user);
                    actualUsers.Add(user);
                }

                byte[] bytes = (pca.UserTokenCacheInternal as ITokenCacheSerializer).SerializeMsalV3();
                _inMemoryCache = Encoding.UTF8.GetString(bytes);

                pca.UserTokenCacheInternal.Accessor.AssertItemCount(
                    expectedAtCount: NumberOfRequests * 2,
                    expectedRtCount: NumberOfRequests,
                    expectedAccountCount: NumberOfRequests,
                    expectedIdtCount: NumberOfRequests,
                    expectedAppMetadataCount: 1);

                IEnumerable <IAccount> accounts = await pca.GetAccountsAsync().ConfigureAwait(false);

                AuthenticationResult[] results;

                // Act
                using (new PerformanceValidator(
                           NumberOfRequests * (2 * CacheAccessPenaltyMs + 100),
                           "AcquireTokenSilent should take roughly 100ms for its internal logic, " +
                           "plus the time needed to access the cache and all the thread context switches"))
                {
                    // execute won't start here because IEnumerable is lazy
                    IEnumerable <Task <AuthenticationResult> > tasks = accounts.Select(acc =>
                                                                                       pca.AcquireTokenSilent(TestConstants.s_scope, acc).ExecuteAsync());

                    // execution starts here
                    Task <AuthenticationResult>[] taskArray = tasks.ToArray();

                    // wait for all requests to complete
                    results = await Task.WhenAll(taskArray).ConfigureAwait(false);
                }

                // Assert
                CollectionAssert.AreEquivalent(
                    actualUsers,
                    results.Select(r => r.Account.Username).ToArray());

                // Expecting the number of cache accesses to be equal to the number of request plus one for GetAccounts
                Assert.AreEqual(NumberOfRequests + 1, _afterAccessCalls);
                Assert.AreEqual(NumberOfRequests + 1, _beforeAccessCalls);

                // Acquire token silent with valid ATs in the cache -> no data is written
                Assert.AreEqual(0, _beforeWriteCalls);
                Assert.AreEqual(0, _afterAccessWriteCalls);
            }
        }
Beispiel #13
0
        public async Task AcquireTokenSilent_ExpiredATs_ParallelRequests_Async()
        {
            // Arrange
            const int NumberOfRequests = 10;

            // The typical HttpMockHandler used by other tests can't deal with parallel request
            ParallelRequestMockHanler httpManager = new ParallelRequestMockHanler();

            PublicClientApplication pca = PublicClientApplicationBuilder
                                          .Create(TestConstants.ClientId)
                                          .WithHttpManager(httpManager)
                                          .BuildConcrete();

            ConfigureCacheSerialization(pca);

            var actualUsers = new List <string>();

            for (int i = 1; i <= NumberOfRequests; i++)
            {
                _tokenCacheHelper.PopulateCache(
                    pca.UserTokenCacheInternal.Accessor,
                    GetUid(i),
                    TestConstants.Utid,
                    displayableId: GetUpn(i),
                    rtSecret: i.ToString(CultureInfo.InvariantCulture), // this will help create a valid response
                    expiredAccessTokens: true);
                actualUsers.Add(GetUpn(i));
            }

            byte[] bytes = (pca.UserTokenCacheInternal as ITokenCacheSerializer).SerializeMsalV3();
            _inMemoryCache = Encoding.UTF8.GetString(bytes);

            pca.UserTokenCacheInternal.Accessor.AssertItemCount(
                expectedAtCount: NumberOfRequests * 2,
                expectedRtCount: NumberOfRequests,
                expectedAccountCount: NumberOfRequests,
                expectedIdtCount: NumberOfRequests,
                expectedAppMetadataCount: 1);

            IEnumerable <IAccount> accounts = await pca.GetAccountsAsync().ConfigureAwait(false);

            AuthenticationResult[] results;

            // Act
            using (new PerformanceValidator(
                       NumberOfRequests *
                       (2 * CacheAccessPenaltyMs + NetworkAccessPenaltyMs /* refresh the RT */ + 100 /* internal logic */) +
                       2 * NetworkAccessPenaltyMs, /* one time discovery calls */
                       "AcquireTokenSilent in parallel should take roughly 100ms for its internal logic, " +
                       "plus the time needed to access the cache, the network, and all the thread context switches"))
            {
                // execute won't start here because IEnumerable is lazy
                IEnumerable <Task <AuthenticationResult> > tasks = accounts.Select(acc =>
                                                                                   pca.AcquireTokenSilent(TestConstants.s_scope, acc).ExecuteAsync());

                // execution starts here
                Task <AuthenticationResult>[] taskArray = tasks.ToArray();

                // wait for all requests to complete
                results = await Task.WhenAll(taskArray).ConfigureAwait(false);
            }

            // Assert
            CollectionAssert.AreEquivalent(
                actualUsers,
                results.Select(r => r.Account.Username).ToArray());

            // Each task will write tokens
            Assert.AreEqual(NumberOfRequests, _beforeWriteCalls);
            Assert.AreEqual(NumberOfRequests, _afterAccessWriteCalls);

            // Expecting the number of cache accesses to be equal to twice the number of requests
            // (one for the initial read access, one for when writing the tokens)
            // plus one for GetAccounts
            Assert.AreEqual(NumberOfRequests * 2 + 1, _afterAccessCalls);
            Assert.AreEqual(NumberOfRequests * 2 + 1, _beforeAccessCalls);
        }
 public MicrosoftAuthentication(AuthenticationSettings authSettings)
 {
     AuthSettings    = authSettings;
     PublicClientApp = PublicClientApplicationBuilder.Create(AuthSettings.ClientId).WithAuthority(AzureCloudInstance.AzurePublic, AuthSettings.Tenant, true).WithRedirectUri("http://localhost").Build();
 }
        public async Task TestSerializationViaAsync()
        {
            int numBeforeAccessCalls = 0;
            int numAfterAccessCalls  = 0;
            int numBeforeWriteCalls  = 0;

            byte[] serializedPayload = null;

            var sb = new StringBuilder();

            using (var harness = CreateTestHarness())
            {
                harness.HttpManager.AddInstanceDiscoveryMockHandler();

                PublicClientApplication pca = PublicClientApplicationBuilder
                                              .Create(TestConstants.ClientId)
                                              .WithAuthority(new Uri(ClientApplicationBase.DefaultAuthority), true)
                                              .WithHttpManager(harness.HttpManager)
                                              .WithTelemetry(new TraceTelemetryConfig())
                                              .BuildConcrete();

                pca.UserTokenCache.SetBeforeAccessAsync(async args =>
                {
                    sb.Append("beforeaccess-");
                    numBeforeAccessCalls++;

                    // Task Delay is so that we have an await within the async callback and also to simulate
                    // some level of time that we did work.
                    await Task.Delay(10).ConfigureAwait(false);
                });
                pca.UserTokenCache.SetAfterAccessAsync(async args =>
                {
                    sb.Append("afteraccess-");
                    numAfterAccessCalls++;
                    serializedPayload = args.TokenCache.SerializeMsalV3();
                    await Task.Delay(10).ConfigureAwait(false);
                });
                pca.UserTokenCache.SetBeforeWriteAsync(async args =>
                {
                    sb.Append("beforewrite-");
                    numBeforeWriteCalls++;
                    await Task.Delay(10).ConfigureAwait(false);
                });


                pca.ServiceBundle.ConfigureMockWebUI(
                    AuthorizationResult.FromUri(pca.AppConfig.RedirectUri + "?code=some-code"));

                harness.HttpManager.AddSuccessTokenResponseMockHandlerForPost(TestConstants.AuthorityCommonTenant);

                AuthenticationResult result = await pca
                                              .AcquireTokenInteractive(TestConstants.s_scope)
                                              .ExecuteAsync(CancellationToken.None)
                                              .ConfigureAwait(false);
            }

            Assert.AreEqual("beforeaccess-beforewrite-afteraccess-", sb.ToString());

            Assert.AreEqual(1, numBeforeAccessCalls);
            Assert.AreEqual(1, numAfterAccessCalls);
            Assert.AreEqual(1, numBeforeWriteCalls);

            Assert.IsNotNull(serializedPayload);
        }
        public static async Task Run()
        {
            /////////////////
            //
            // Configuration
            //
            /////////////////

            AzureAdOptions azureAdOptions = new AzureAdOptions();

            var settingsFilename = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "appsettings.json");
            var builder          = new ConfigurationBuilder()
                                   .AddJsonFile(settingsFilename, optional: false)
                                   .AddUserSecrets <Program>();
            var config = builder.Build();

            config.Bind("AzureAd", azureAdOptions);

            ////////////////////////////
            //
            // Graph Client with Logger
            //
            ////////////////////////////

            var logger = new StringBuilderHttpMessageLogger();

            /*
             *  Could also use the Console if preferred...
             *
             *  var logger = new ConsoleHttpMessageLogger();
             */

            var pca = PublicClientApplicationBuilder
                      .Create(azureAdOptions.ClientId)
                      .WithTenantId(azureAdOptions.TenantId)
                      .Build();

            var scopes = new string[] { "https://graph.microsoft.com/Mail.Read" };
            IAuthenticationProvider ap = new DeviceCodeProvider(pca, scopes);

            using (LoggingMessageHandler loggingHandler = new LoggingMessageHandler(logger))
                using (HttpProvider hp = new HttpProvider(loggingHandler, false, new Serializer()))
                {
                    GraphServiceClient graphServiceClient = new GraphServiceClient(ap, hp);


                    ////////////////////////////
                    //
                    // Setup is complete, run the sample
                    //
                    ////////////////////////////

                    var messages =
                        await graphServiceClient
                        .Me
                        .Messages
                        .Request()
                        .Top(1)
                        .GetAsync();

                    Console.WriteLine($"ID: {messages.CurrentPage[0].Id}");

                    Console.WriteLine();

                    var messagesI =
                        await graphServiceClient
                        .Me
                        .Messages
                        .Request()
                        .WithImmutableId()
                        .Top(1)
                        .GetAsync();

                    Console.WriteLine($"ImmutableId: {messagesI.CurrentPage[0].Id}");
                    Console.WriteLine();

                    Console.WriteLine("Press enter to show log");
                    Console.ReadLine();
                    Console.WriteLine();
                    Console.WriteLine(logger.GetLog());
                }
        }
Beispiel #17
0
        private async Task <AuthenticationResult> AcquireTokenAsync(int userIndex, Metrics localMetrics)
        {
            var scopes = new string[] { _options.ApiScopes };
            var upn    = $"{_options.UsernamePrefix}{userIndex}@{_options.TenantDomain}";

            var builder = PublicClientApplicationBuilder
                          .Create(_options.ClientId)
                          .WithAuthority(TestConstants.AadInstance, TestConstants.Organizations);

            if (_options.EnableMsalLogging)
            {
                builder.WithLogging(Logger.Log, LogLevel.Error, false);
            }

            var msalPublicClient = builder.Build();

            TokenCacheHelper.EnableSerialization(msalPublicClient.UserTokenCache);

            AuthenticationResult authResult = null;

            try
            {
                try
                {
                    var      identifier = _userAccountIdentifiers[userIndex];
                    IAccount account    = null;
                    if (identifier != null)
                    {
                        var stopwatch = new Stopwatch();
                        stopwatch.Start();
                        account = await msalPublicClient.GetAccountAsync(identifier).ConfigureAwait(false);

                        stopwatch.Stop();
                        localMetrics.TotalMsalLookupTimeInMilliseconds += stopwatch.Elapsed.TotalMilliseconds;
                    }

                    authResult = await msalPublicClient.AcquireTokenSilent(scopes, account).ExecuteAsync(CancellationToken.None).ConfigureAwait(false);

                    return(authResult);
                }
                catch (MsalUiRequiredException)
                {
                    // Delay to prevent spamming the STS with calls.
                    await Task.Delay(_options.RequestDelayInMilliseconds);

                    authResult = await msalPublicClient.AcquireTokenByUsernamePassword(
                        scopes,
                        upn,
                        new NetworkCredential(
                            upn,
                            _options.UserPassword).SecurePassword)
                                 .ExecuteAsync(CancellationToken.None)
                                 .ConfigureAwait(false);

                    _userAccountIdentifiers[userIndex] = authResult.Account.HomeAccountId.Identifier;
                    return(authResult);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Exception in AcquireTokenAsync: {ex}");
            }
            return(authResult);
        }
Beispiel #18
0
        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())
            {
                httpManager.AddInstanceDiscoveryMockHandler();

                var authorityUri = new Uri(
                    string.Format(
                        CultureInfo.InvariantCulture,
                        "https://{0}/common",
                        MsalTestConstants.ProductionNotPrefEnvironmentAlias));

                var app = PublicClientApplicationBuilder
                          .Create(MsalTestConstants.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",
                                                MsalTestConstants.ProductionPrefNetworkEnvironment),
                    ExpectedMethod  = HttpMethod.Get,
                    ResponseMessage = MockHelpers.CreateOpenIdConfigurationResponse(MsalTestConstants.AuthorityHomeTenant)
                });

                // mock webUi authorization
                MsalMockHelpers.ConfigureMockWebUI(
                    app.ServiceBundle.PlatformProxy,
                    AuthorizationResult.FromUri(app.AppConfig.RedirectUri + "?code=some-code"), null, MsalTestConstants.ProductionPrefNetworkEnvironment);

                // mock token request
                httpManager.AddMockHandler(new MockHttpMessageHandler
                {
                    ExpectedUrl = string.Format(CultureInfo.InvariantCulture, "https://{0}/home/oauth2/v2.0/token",
                                                MsalTestConstants.ProductionPrefNetworkEnvironment),
                    ExpectedMethod  = HttpMethod.Post,
                    ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage()
                });

                AuthenticationResult result = app.AcquireTokenInteractive(MsalTestConstants.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, MsalTestConstants.ProductionPrefCacheEnvironment).ConfigureAwait(false);

                // silent request targeting at, should return at from cache for any environment alias
                foreach (var envAlias in MsalTestConstants.ProdEnvAliases)
                {
                    result = await app
                             .AcquireTokenSilent(
                        MsalTestConstants.Scope,
                        app.GetAccountsAsync().Result.First())
                             .WithAuthority(string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/", envAlias, MsalTestConstants.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",
                                                MsalTestConstants.ProductionPrefNetworkEnvironment, MsalTestConstants.Utid),
                    ExpectedMethod  = HttpMethod.Get,
                    ResponseMessage = MockHelpers.CreateOpenIdConfigurationResponse(MsalTestConstants.AuthorityUtidTenant)
                });

                // silent request targeting rt should find rt in cache for authority with any environment alias
                foreach (var envAlias in MsalTestConstants.ProdEnvAliases)
                {
                    result = null;

                    httpManager.AddMockHandler(new MockHttpMessageHandler()
                    {
                        ExpectedUrl = string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/oauth2/v2.0/token",
                                                    MsalTestConstants.ProductionPrefNetworkEnvironment, MsalTestConstants.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(
                            MsalTestConstants.ScopeForAnotherResource,
                            (await app.GetAccountsAsync().ConfigureAwait(false)).First())
                                 .WithAuthority(string.Format(CultureInfo.InvariantCulture, "https://{0}/{1}/", envAlias, MsalTestConstants.Utid))
                                 .WithForceRefresh(false)
                                 .ExecuteAsync(CancellationToken.None).ConfigureAwait(false);
                    }
                    catch (MsalUiRequiredException)
                    {
                    }
                    catch (Exception)
                    {
                        Assert.Fail();
                    }

                    Assert.IsNull(result);
                }
            }
        }
Beispiel #19
0
        private async Task RunOnBehalfOfTestAsync(LabResponse labResponse)
        {
            LabUser user = labResponse.User;
            string  oboHost;
            string  secret;
            string  authority;
            string  publicClientID;
            string  confidentialClientID;

            string[] oboScope;

            switch (labResponse.User.AzureEnvironment)
            {
            case AzureEnvironment.azureusgovernment:
                oboHost              = ArlingtonCloudHost;
                secret               = _keyVault.GetSecret(TestConstants.MsalArlingtonOBOKeyVaultUri).Value;
                authority            = labResponse.Lab.Authority + "organizations";
                publicClientID       = ArlingtonPublicClientIDOBO;
                confidentialClientID = ArlingtonConfidentialClientIDOBO;
                oboScope             = s_arlingtonOBOServiceScope;
                break;

            default:
                oboHost              = PublicCloudHost;
                secret               = _keyVault.GetSecret(TestConstants.MsalOBOKeyVaultUri).Value;
                authority            = TestConstants.AuthorityOrganizationsTenant;
                publicClientID       = PublicCloudPublicClientIDOBO;
                confidentialClientID = PublicCloudConfidentialClientIDOBO;
                oboScope             = s_publicCloudOBOServiceScope;
                break;
            }

            //TODO: acquire scenario specific client ids from the lab response

            SecureString securePassword = new NetworkCredential("", user.GetOrFetchPassword()).SecurePassword;

            var msalPublicClient = PublicClientApplicationBuilder.Create(publicClientID)
                                   .WithAuthority(authority)
                                   .WithRedirectUri(TestConstants.RedirectUri)
                                   .WithTestLogging()
                                   .Build();

            var builder = msalPublicClient.AcquireTokenByUsernamePassword(oboScope, user.Upn, securePassword);

            builder.WithAuthority(authority);

            var authResult = await builder.ExecuteAsync().ConfigureAwait(false);

            var confidentialApp = ConfidentialClientApplicationBuilder
                                  .Create(confidentialClientID)
                                  .WithAuthority(new Uri(oboHost + authResult.TenantId), true)
                                  .WithClientSecret(secret)
                                  .WithTestLogging()
                                  .Build();

            var userCacheRecorder = confidentialApp.UserTokenCache.RecordAccess();

            UserAssertion userAssertion = new UserAssertion(authResult.AccessToken);

            string atHash = userAssertion.AssertionHash;

            authResult = await confidentialApp.AcquireTokenOnBehalfOf(s_scopes, userAssertion)
                         .ExecuteAsync(CancellationToken.None)
                         .ConfigureAwait(false);

            MsalAssert.AssertAuthResult(authResult, user);
            Assert.AreEqual(atHash, userCacheRecorder.LastAfterAccessNotificationArgs.SuggestedCacheKey);

            await confidentialApp.GetAccountsAsync().ConfigureAwait(false);

            Assert.IsNull(userCacheRecorder.LastAfterAccessNotificationArgs.SuggestedCacheKey);
        }
Beispiel #20
0
        /// <summary>
        /// Generates and returns Access token
        /// </summary>
        /// <param name="appSettings">Contains appsettings.json configuration values</param>
        /// <returns></returns>
        public static string GetAccessToken(IOptions <ConfigurationModel> appSettings)
        {
            AuthenticationResult authenticationResult = null;

            if (appSettings.Value.AuthenticationMode.Equals("masteruser", StringComparison.InvariantCultureIgnoreCase))
            {
                // Create a public client to authorize the app with the AAD app
                IPublicClientApplication clientApp = PublicClientApplicationBuilder.Create(appSettings.Value.ClientId).WithAuthority(appSettings.Value.AuthorityUri).Build();
                var userAccounts = clientApp.GetAccountsAsync().Result;
                try
                {
                    // Retrieve Access token from cache if available
                    authenticationResult = clientApp.AcquireTokenSilent(appSettings.Value.Scope, userAccounts.FirstOrDefault()).ExecuteAsync().Result;
                }
                catch (MsalUiRequiredException)
                {
                    try
                    {
                        SecureString password = new SecureString();
                        foreach (var key in appSettings.Value.PbiPassword)
                        {
                            password.AppendChar(key);
                        }
                        authenticationResult = clientApp.AcquireTokenByUsernamePassword(appSettings.Value.Scope, appSettings.Value.PbiUsername, password).ExecuteAsync().Result;
                    }
                    catch (MsalException)
                    {
                        throw;
                    }
                }
            }
            else if (appSettings.Value.AuthenticationMode.Equals("serviceprincipal", StringComparison.InvariantCultureIgnoreCase))
            {
                // For app only authentication, we need the specific tenant id in the authority url
                var tenantSpecificUrl = appSettings.Value.AuthorityUri.Replace("organizations", appSettings.Value.TenantId);

                // Create a confidetial client to authorize the app with the AAD app
                IConfidentialClientApplication clientApp = ConfidentialClientApplicationBuilder
                                                           .Create(appSettings.Value.ClientId)
                                                           .WithClientSecret(appSettings.Value.ClientSecret)
                                                           .WithAuthority(tenantSpecificUrl)
                                                           .Build();
                try
                {
                    // Make a client call if Access token is not available in cache
                    authenticationResult = clientApp.AcquireTokenForClient(appSettings.Value.Scope).ExecuteAsync().Result;
                }
                catch (MsalException)
                {
                    throw;
                }
            }

            try
            {
                return(authenticationResult.AccessToken);
            }
            catch (Exception)
            {
                throw;
            }
        }
Beispiel #21
0
        public void UnifiedCache_MsalStoresToAndReadRtFromAdalCache()
        {
            using (var mocks = new MockHttpAndServiceBundle())
            {
                var httpManager = mocks.HttpManager;
                httpManager.AddInstanceDiscoveryMockHandler();

                var app = PublicClientApplicationBuilder.Create(TestConstants.ClientId)
                          .WithAuthority(new Uri(ClientApplicationBase.DefaultAuthority), true)
                          .WithHttpManager(httpManager)
                          .WithTelemetry(new TraceTelemetryConfig())
                          .WithUserTokenLegacyCachePersistenceForTest(
                    new TestLegacyCachePersistance())
                          .BuildConcrete();


                app.ServiceBundle.ConfigureMockWebUI(
                    AuthorizationResult.FromUri(app.AppConfig.RedirectUri + "?code=some-code"));

                HttpResponseMessage response = MockHelpers.CreateSuccessTokenResponseMessageWithUid(
                    TestConstants.Uid,
                    TestConstants.Utid,
                    "*****@*****.**");

                httpManager.AddResponseMockHandlerForPost(response);

                AuthenticationResult result = app.AcquireTokenInteractive(TestConstants.s_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 authority = Microsoft.Identity.Client.Instance.Authority.CreateAuthorityForRequest(
                    requestContext.ServiceBundle.Config.AuthorityInfo, null);

                AuthenticationRequestParameters reqParams = new AuthenticationRequestParameters(
                    mocks.ServiceBundle,
                    app.UserTokenCacheInternal,
                    new Client.ApiConfig.Parameters.AcquireTokenCommonParameters(),
                    requestContext,
                    authority);

                var accounts = app.UserTokenCacheInternal.GetAccountsAsync(reqParams).Result;
                foreach (IAccount account in accounts)
                {
                    app.UserTokenCacheInternal.RemoveMsalAccountWithNoLocks(account, requestContext);
                }

                Assert.AreEqual(0, httpManager.QueueSize);

                httpManager.AddMockHandler(
                    new MockHttpMessageHandler()
                {
                    ExpectedMethod   = HttpMethod.Post,
                    ExpectedPostData = new Dictionary <string, string>()
                    {
                        { "grant_type", "refresh_token" }
                    },
                    ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage(
                        TestConstants.UniqueId,
                        TestConstants.DisplayableId,
                        TestConstants.s_scope.ToArray())
                });

                // Using RT from Adal cache for silent call
                AuthenticationResult result1 = app
                                               .AcquireTokenSilent(TestConstants.s_scope, result.Account)
                                               .WithAuthority(TestConstants.AuthorityCommonTenant)
                                               .WithForceRefresh(false)
                                               .ExecuteAsync(CancellationToken.None)
                                               .Result;

                Assert.IsNotNull(result1);
            }
        }
Beispiel #22
0
        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().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
            }
        }
Beispiel #23
0
        private async Task <AuthenticationResult> RunTestForUserAsync(LabResponse labResponse, bool directToAdfs = false)
        {
            IPublicClientApplication pca;

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

            var userCacheAccess = pca.UserTokenCache.RecordAccess();

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

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

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

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

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

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

            userCacheAccess.AssertAccessCounts(2, 3);

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

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

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

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

            Assert.IsFalse(userCacheAccess.LastNotificationArgs.IsApplicationCache);

            return(result);
        }
Beispiel #24
0
        public async Task AcquireTokenByObo_NormalOboThenLongRunningAcquire_WithTheSameKey_TestAsync()
        {
            var user1 = (await LabUserHelper.GetSpecificUserAsync("*****@*****.**").ConfigureAwait(false)).User;
            var pca   = PublicClientApplicationBuilder
                        .Create(PublicClientID)
                        .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs)
                        .Build();

            var userAuthResult = await pca
                                 .AcquireTokenByUsernamePassword(s_oboServiceScope, user1.Upn, new NetworkCredential("", user1.GetOrFetchPassword()).SecurePassword)
                                 .ExecuteAsync(CancellationToken.None)
                                 .ConfigureAwait(false);

            var cca = BuildCCA(userAuthResult.TenantId);

            UserAssertion userAssertion = new UserAssertion(userAuthResult.AccessToken);
            string        oboCacheKey   = userAssertion.AssertionHash;

            // AcquireNormal - AT from IdP via OBO flow (only new AT cached, no RT in cache)
            var result = await cca.AcquireTokenOnBehalfOf(s_scopes, userAssertion).ExecuteAsync().ConfigureAwait(false);

            Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource);
            Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count);
            Assert.AreEqual(0, cca.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count);

            // AcquireLR - AT from cache
            result = await cca.AcquireTokenInLongRunningProcess(s_scopes, oboCacheKey).ExecuteAsync().ConfigureAwait(false);

            Assert.AreEqual(TokenSource.Cache, result.AuthenticationResultMetadata.TokenSource);

            // Expire AT
            TokenCacheHelper.ExpireAllAccessTokens(cca.UserTokenCacheInternal);

            // AcquireLR - throws because no RT
            var exception = await AssertException.TaskThrowsAsync <MsalClientException>(
                () => cca.AcquireTokenInLongRunningProcess(s_scopes.ToArray(), oboCacheKey)
                .ExecuteAsync())
                            .ConfigureAwait(false);

            Assert.AreEqual(MsalError.OboCacheKeyNotInCacheError, exception.ErrorCode);

            // Expire AT
            TokenCacheHelper.ExpireAllAccessTokens(cca.UserTokenCacheInternal);

            // InitiateLR - AT from IdP via OBO flow (new AT, RT cached)
            result = await cca.InitiateLongRunningProcessInWebApi(s_scopes, userAuthResult.AccessToken, ref oboCacheKey)
                     .ExecuteAsync().ConfigureAwait(false);

            Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource);
            Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count);
            Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count);

            // Expire AT
            TokenCacheHelper.ExpireAllAccessTokens(cca.UserTokenCacheInternal);

            // AcquireLR - AT from IdP via RT flow (new AT, RT cached)
            result = await cca.AcquireTokenInLongRunningProcess(s_scopes, oboCacheKey).ExecuteAsync().ConfigureAwait(false);

            Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource);
            Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count);
            Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count);
        }
Beispiel #25
0
        [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

                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.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.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());
            }
        }
Beispiel #26
0
        private async Task <IConfidentialClientApplication> RunOnBehalfOfTestAsync(
            LabUser user,
            bool silentCallShouldSucceed,
            bool forceRefresh = false)
        {
            SecureString         securePassword = new NetworkCredential("", user.GetOrFetchPassword()).SecurePassword;
            AuthenticationResult authResult;

            var pca = PublicClientApplicationBuilder
                      .Create(PublicClientID)
                      .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs)
                      .WithTestLogging()
                      .Build();

            s_inMemoryTokenCache.Bind(pca.UserTokenCache);
            try
            {
                authResult = await pca
                             .AcquireTokenSilent(s_oboServiceScope, user.Upn)
                             .ExecuteAsync()
                             .ConfigureAwait(false);

                Assert.AreEqual(TokenSource.Cache, authResult.AuthenticationResultMetadata.TokenSource);
            }
            catch (MsalUiRequiredException)
            {
                Assert.IsFalse(silentCallShouldSucceed, "ATS should have found a token, but it didn't");
                authResult = await pca
                             .AcquireTokenByUsernamePassword(s_oboServiceScope, user.Upn, securePassword)
                             .ExecuteAsync(CancellationToken.None)
                             .ConfigureAwait(false);

                Assert.AreEqual(TokenSource.IdentityProvider, authResult.AuthenticationResultMetadata.TokenSource);
            }

            MsalAssert.AssertAuthResult(authResult, user);
            Assert.IsTrue(authResult.Scopes.Any(s => string.Equals(s, s_oboServiceScope.Single(), StringComparison.OrdinalIgnoreCase)));

            var cca = ConfidentialClientApplicationBuilder
                      .Create(OboConfidentialClientID)
                      .WithAuthority(new Uri("https://login.microsoftonline.com/" + authResult.TenantId), true)
                      .WithTestLogging(out HttpSnifferClientFactory factory)
                      .WithClientSecret(_confidentialClientSecret)
                      .Build();

            s_inMemoryTokenCache.Bind(cca.UserTokenCache);

            authResult = await cca.AcquireTokenOnBehalfOf(s_scopes, new UserAssertion(authResult.AccessToken))
                         .WithForceRefresh(forceRefresh)
                         .WithCcsRoutingHint("597f86cd-13f3-44c0-bece-a1e77ba43228", "f645ad92-e38d-4d1a-b510-d1b09a74a8ca")
                         .ExecuteAsync(CancellationToken.None)
                         .ConfigureAwait(false);

            if (!forceRefresh)
            {
                Assert.AreEqual(
                    silentCallShouldSucceed,
                    authResult.AuthenticationResultMetadata.TokenSource == TokenSource.Cache);
            }
            else
            {
                Assert.AreEqual(TokenSource.IdentityProvider, authResult.AuthenticationResultMetadata.TokenSource);
            }

            MsalAssert.AssertAuthResult(authResult, user);
            Assert.IsNotNull(authResult.IdToken); // https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/1950
            Assert.IsTrue(authResult.Scopes.Any(s => string.Equals(s, s_scopes.Single(), StringComparison.OrdinalIgnoreCase)));
            AssertExtraHTTPHeadersAreSent(factory);

            return(cca);
        }
Beispiel #27
0
        public static InteractiveAuthenticationProvider GetCredentialProvider()
        {
            IPublicClientApplication publicClientApplication = PublicClientApplicationBuilder.Create(clientId).WithTenantId(tenantId).WithDefaultRedirectUri().Build();

            return(new InteractiveAuthenticationProvider(publicClientApplication));
        }
Beispiel #28
0
        public async Task OboAndSilent_Async(bool serializeCache, bool usePartitionedSerializationCache)
        {
            // Setup: Get lab users, create PCA and get user tokens
            var user1 = (await LabUserHelper.GetSpecificUserAsync("*****@*****.**").ConfigureAwait(false)).User;
            var user2 = (await LabUserHelper.GetSpecificUserAsync("*****@*****.**").ConfigureAwait(false)).User;
            var partitionedInMemoryTokenCache    = new InMemoryPartitionedTokenCache();
            var nonPartitionedInMemoryTokenCache = new InMemoryTokenCache();
            var oboTokens = new HashSet <string>();

            var pca = PublicClientApplicationBuilder
                      .Create(PublicClientID)
                      .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs)
                      .Build();

            var user1AuthResult = await pca
                                  .AcquireTokenByUsernamePassword(s_oboServiceScope, user1.Upn, new NetworkCredential("", user1.GetOrFetchPassword()).SecurePassword)
                                  .ExecuteAsync(CancellationToken.None)
                                  .ConfigureAwait(false);

            var user2AuthResult = await pca
                                  .AcquireTokenByUsernamePassword(s_oboServiceScope, user2.Upn, new NetworkCredential("", user2.GetOrFetchPassword()).SecurePassword)
                                  .ExecuteAsync(CancellationToken.None)
                                  .ConfigureAwait(false);

            Assert.AreEqual(user1AuthResult.TenantId, user2AuthResult.TenantId);

            var cca = CreateCCA();

            // Asserts
            // Silent calls should throw
            await AssertException.TaskThrowsAsync <MsalUiRequiredException>(() =>
                                                                            cca.AcquireTokenSilent(s_scopes, user1.Upn)
                                                                            .ExecuteAsync(CancellationToken.None)
                                                                            ).ConfigureAwait(false);

            await AssertException.TaskThrowsAsync <MsalUiRequiredException>(() =>
                                                                            cca.AcquireTokenSilent(s_scopes, user2.Upn)
                                                                            .ExecuteAsync(CancellationToken.None)
                                                                            ).ConfigureAwait(false);

            // User1 - no AT, RT in cache - retrieves from IdP
            var authResult = await cca.AcquireTokenOnBehalfOf(s_scopes, new UserAssertion(user1AuthResult.AccessToken))
                             .ExecuteAsync(CancellationToken.None)
                             .ConfigureAwait(false);

            Assert.AreEqual(TokenSource.IdentityProvider, authResult.AuthenticationResultMetadata.TokenSource);
            Assert.AreEqual(CacheRefreshReason.NoCachedAccessToken, authResult.AuthenticationResultMetadata.CacheRefreshReason);
            oboTokens.Add(authResult.AccessToken);

            // User1 - finds AT in cache
            authResult = await cca.AcquireTokenOnBehalfOf(s_scopes, new UserAssertion(user1AuthResult.AccessToken))
                         .ExecuteAsync(CancellationToken.None)
                         .ConfigureAwait(false);

            Assert.AreEqual(TokenSource.Cache, authResult.AuthenticationResultMetadata.TokenSource);
            Assert.AreEqual(CacheRefreshReason.NotApplicable, authResult.AuthenticationResultMetadata.CacheRefreshReason);
            oboTokens.Add(authResult.AccessToken);

            // User2 - no AT, RT - retrieves from IdP
            authResult = await cca.AcquireTokenOnBehalfOf(s_scopes, new UserAssertion(user2AuthResult.AccessToken))
                         .ExecuteAsync(CancellationToken.None)
                         .ConfigureAwait(false);

            Assert.AreEqual(TokenSource.IdentityProvider, authResult.AuthenticationResultMetadata.TokenSource);
            Assert.AreEqual(CacheRefreshReason.NoCachedAccessToken, authResult.AuthenticationResultMetadata.CacheRefreshReason);
            oboTokens.Add(authResult.AccessToken);

            // User2 - finds AT in cache
            authResult = await cca.AcquireTokenOnBehalfOf(s_scopes, new UserAssertion(user2AuthResult.AccessToken))
                         .ExecuteAsync(CancellationToken.None)
                         .ConfigureAwait(false);

            Assert.AreEqual(TokenSource.Cache, authResult.AuthenticationResultMetadata.TokenSource);
            Assert.AreEqual(CacheRefreshReason.NotApplicable, authResult.AuthenticationResultMetadata.CacheRefreshReason);
            oboTokens.Add(authResult.AccessToken);

            Assert.AreEqual(2, oboTokens.Count);

            // Silent calls should throw
            await AssertException.TaskThrowsAsync <MsalUiRequiredException>(() =>
                                                                            cca.AcquireTokenSilent(s_scopes, user1.Upn)
                                                                            .ExecuteAsync(CancellationToken.None)
                                                                            ).ConfigureAwait(false);

            await AssertException.TaskThrowsAsync <MsalUiRequiredException>(() =>
                                                                            cca.AcquireTokenSilent(s_scopes, user2.Upn)
                                                                            .ExecuteAsync(CancellationToken.None)
                                                                            ).ConfigureAwait(false);

            IConfidentialClientApplication CreateCCA()
            {
                var app = ConfidentialClientApplicationBuilder
                          .Create(OboConfidentialClientID)
                          .WithAuthority(new Uri($"https://login.microsoftonline.com/{user1AuthResult.TenantId}"), true)
                          .WithClientSecret(_confidentialClientSecret)
                          .WithLegacyCacheCompatibility(false)
                          .Build();

                if (serializeCache)
                {
                    if (usePartitionedSerializationCache)
                    {
                        partitionedInMemoryTokenCache.Bind(app.UserTokenCache);
                    }
                    else
                    {
                        nonPartitionedInMemoryTokenCache.Bind(app.UserTokenCache);
                    }
                }

                return(app);
            }
        }
Beispiel #29
0
        protected override async void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            // Create your application here
            SetContentView(Resource.Layout.activity_main);

            var check = System.Threading.Thread.CurrentThread.Name;


            callGraphButton = (Button)FindViewById(Resource.Id.callGraph);
            signOutButton   = (Button)FindViewById(Resource.Id.clearCache);


            /*            callGraphButton.Click += (sender, e) =>
             *          {
             *              //      onCallGraphClicked();
             *          };
             *
             *          signOutButton.Click += (sender, e) =>
             *          {
             *              //     onSignOutClicked();
             *          };*/

            //sampleApp = "";
            /* Configure your sample app and save state for this activity */
            sampleApp = PublicClientApplicationBuilder.Create(ClientId).WithRedirectUri(reDirect).Build();

            var scopes = mScopes.Split(' ');

            accessToken = string.Empty;

            /*  try
             * {
             *    IEnumerable<IAccount> accounts = await sampleApp.GetAccountsAsync();
             *
             *    if (accounts.Count() > 0)
             *    {
             *        IAccount firstAccount = accounts.FirstOrDefault();
             *        silentAuthResult = await sampleApp.AcquireTokenSilent(scopes, firstAccount).ExecuteAsync();
             *
             *        await RefreshUserDataAsync(silentAuthResult.AccessToken).ConfigureAwait(false);
             *
             *        Console.WriteLine("User already signed in.");
             *        Console.WriteLine($"Access token: {silentAuthResult.AccessToken}");
             *        accessToken = silentAuthResult.AccessToken;
             *    }
             * }
             *
             * catch (MsalUiRequiredException)
             * {
             *    // This exception is thrown when an interactive sign-in is required.
             *    Console.WriteLine("Silent token request failed, user needs to sign-in");
             * }*/

            if (string.IsNullOrEmpty(accessToken))
            {
                // Prompt the user to sign-in
                var interactiveRequest = await sampleApp.AcquireTokenInteractive(scopes).WithParentActivityOrWindow(this).ExecuteAsync();

                await RefreshUserDataAsync(interactiveRequest.AccessToken);

                // var authResult = await interactiveRequest.WithParentActivityOrWindow(this).ExecuteAsync();
                Console.WriteLine("Access Token: {0}", arg0: interactiveRequest.AccessToken);

                var intent = new Intent(this, typeof(OptionsforKids));
                StartActivity(intent);
                AuthUIParent = this;
            }
            //code to create buttons dynamically

            LinearLayout linearLayout = FindViewById <LinearLayout>(Resource.Id.grace);

            for (int i = 0; i < 15; i++)
            {
                //You create the instance of your view in this case your Button
                Button button = new Button(this);
                button.Text = "grace";
                button.SetBackgroundColor(Android.Graphics.Color.Black);
                button.SetTextColor(Android.Graphics.Color.White);

                //define the button layout
                LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);

                //in case you want to modify other properties of the LayoutParams you use the object
                layoutParams.BottomMargin = 5;

                //Assign the layoutParams to the Button.
                button.LayoutParameters = layoutParams;

                //If you want to do something with the buttons you create you add the handle here
                //button.Click += (sender, e) => DoSomething(id);

                //Add the button as a child of your ViewGroup
                var check2 = System.Threading.Thread.CurrentThread.Name;
                RunOnUiThread(() =>
                {
                    linearLayout.AddView(button);
                });
            }
        }
 public OneDrive2FileStorage()
 {
     _publicClientApp = PublicClientApplicationBuilder.Create(ClientID)
                        .WithRedirectUri($"msal{ClientID}://auth")
                        .Build();
 }