/// <summary>
        /// Returns an access token depending on the type requested for testing.
        /// </summary>
        /// <returns></returns>
        private Task <AppAuthenticationResult> AcquireTokenAsync()
        {
            AppAuthenticationResult authResult;

            switch (_mockAuthenticationContextTestType)
            {
            case MockAuthenticationContextTestType.AcquireTokenSilentAsyncFail:
            case MockAuthenticationContextTestType.AcquireTokenAsyncClientCertificateFail:
            case MockAuthenticationContextTestType.AcquireTokenAsyncClientCredentialFail:
            case MockAuthenticationContextTestType.AcquireTokenAsyncUserCredentialFail:
                return(Task.FromResult <AppAuthenticationResult>(null));

            case MockAuthenticationContextTestType.AcquireInvalidTokenAsyncFail:
                authResult = AppAuthenticationResult.Create(TokenHelper.GetInvalidAppToken());
                return(Task.FromResult(authResult));

            case MockAuthenticationContextTestType.AcquireTokenAsyncException:
                throw new Exception(Constants.AdalException);

            case MockAuthenticationContextTestType.AcquireTokenSilentAsyncSuccess:
            case MockAuthenticationContextTestType.AcquireTokenAsyncUserCredentialSuccess:
                authResult = AppAuthenticationResult.Create(TokenHelper.GetUserToken());
                return(Task.FromResult(authResult));

            case MockAuthenticationContextTestType.AcquireTokenAsyncClientCertificateSuccess:
            case MockAuthenticationContextTestType.AcquireTokenAsyncClientCredentialSuccess:
                authResult = AppAuthenticationResult.Create(TokenHelper.GetAppToken());
                return(Task.FromResult(authResult));
            }

            return(null);
        }
Exemplo n.º 2
0
        public async Task GetAppAuthResultCacheTest()
        {
            // Create two instances of AzureServiceTokenProvider based on AzureCliAccessTokenProvider.
            MockProcessManager          mockProcessManager          = new MockProcessManager(MockProcessManager.MockProcessManagerRequestType.Success);
            AzureCliAccessTokenProvider azureCliAccessTokenProvider = new AzureCliAccessTokenProvider(mockProcessManager);
            AzureServiceTokenProvider   azureServiceTokenProvider   = new AzureServiceTokenProvider(azureCliAccessTokenProvider);
            AzureServiceTokenProvider   azureServiceTokenProvider1  = new AzureServiceTokenProvider(azureCliAccessTokenProvider);

            List <Task> tasks = new List <Task>();

            // ManualResetEvent will enable testing of SemaphoreSlim used in AzureServiceTokenProvider.
            ManualResetEvent manualResetEvent = new ManualResetEvent(false);

            // Use AzureServiceTokenProviders to get tokens in parallel.
            for (int i = 0; i < 5; i++)
            {
                Task task = Task.Run(async delegate
                {
                    // This will prevent the next line from running, until manualResetEvent.Set() is called.
                    // This will ensure all GetAccessTokenAsync calls are made at once.
                    manualResetEvent.WaitOne();

                    await azureServiceTokenProvider.GetAccessTokenAsync(Constants.KeyVaultResourceId);
                });

                tasks.Add(task);

                Task task1 = Task.Run(async delegate
                {
                    manualResetEvent.WaitOne();

                    // This is using the other instance of AzureServiceTokenProvider.
                    await azureServiceTokenProvider1.GetAccessTokenAsync(Constants.KeyVaultResourceId);
                });

                tasks.Add(task1);
            }

            // This will cause GetAccessTokenAsync calls to be made concurrently.
            manualResetEvent.Set();
            await Task.WhenAll(tasks);

            // Even though multiple calls are made to get token concurrently, using two different instances, the process manager should only be called once.
            // This test tells us that the cache is working as intended.
            Assert.Equal(1, mockProcessManager.HitCount);

            // Get the token again. This will test if the cache call before semaphore use is working as intended.
            for (int i = 0; i < 5; i++)
            {
                tasks.Add(azureServiceTokenProvider.GetAccessTokenAsync(Constants.KeyVaultResourceId));
            }

            await Task.WhenAll(tasks);

            // The hit count should still be 1, since the token should be fetched from cache.
            Assert.Equal(1, mockProcessManager.HitCount);

            // Update the cache entry, to simulate token expiration. This updated token will expire in just less than 5 minutes.
            // In a real scenario, the token will expire after some time.
            // AppAuthResultCache should not return this, since it is about to expire.
            var tokenResponse = TokenResponse.Parse(TokenHelper.GetUserTokenResponse(5 * 60 - 2));
            var authResult    = AppAuthenticationResult.Create(tokenResponse, TokenResponse.DateFormat.DateTimeString);

            AppAuthResultCache.AddOrUpdate("ConnectionString:;Authority:;Resource:https://vault.azure.net/",
                                           new Tuple <AppAuthenticationResult, Principal>(authResult, null));

            // Get the token again.
            for (int i = 0; i < 5; i++)
            {
                tasks.Add(azureServiceTokenProvider.GetAccessTokenAsync(Constants.KeyVaultResourceId));
            }

            await Task.WhenAll(tasks);

            // Hit count should be 2 now, since new token should have been aquired.
            Assert.Equal(2, mockProcessManager.HitCount);
        }