private async Task<string> GetAccessTokenForResourceAsync(string resource, ClaimsPrincipal user)
        {
            var userId = user.GetObjectIdentifierValue();
            var issuerValue = user.GetIssuerValue();
            var userName = user.Identity?.Name;

            try
            {
                _logger.BearerTokenAcquisitionStarted(resource, userName, issuerValue);
                var authContext = await CreateAuthenticationContext(user)
                    .ConfigureAwait(false);
                var result = await authContext.AcquireTokenSilentAsync(
                    resource,
                    await _credentialService.GetCredentialsAsync().ConfigureAwait(false),
                    new UserIdentifier(userId, UserIdentifierType.UniqueId))
                    .ConfigureAwait(false);

                _logger.BearerTokenAcquisitionSucceeded(resource, userName, issuerValue);

                return result.AccessToken;
            }
            catch (AdalException ex)
            {
                _logger.BearerTokenAcquisitionFailed(resource, userName, issuerValue, ex);
                throw new AuthenticationException($"AcquireTokenSilentAsync failed for user: {userId}", ex);
            }
        }
        /// <summary>
        /// Builds the cache key to use for this item in the distributed cache.
        /// </summary>
        /// <param name="claimsPrincipal">A <see cref="System.Security.Claims.ClaimsPrincipal"/> for the signed in user</param>
        /// <returns>Cache key for this item.</returns>
        private static string BuildCacheKey(ClaimsPrincipal claimsPrincipal)
        {
            Guard.ArgumentNotNull(claimsPrincipal, nameof(claimsPrincipal));

            string clientId = claimsPrincipal.FindFirstValue("aud", true);
            return string.Format(
                "UserId:{0}::ClientId:{1}",
                claimsPrincipal.GetObjectIdentifierValue(),
                clientId);
        }
        /// <summary>
        /// This method acquires an access token using an authorization code and ADAL. The access token is then cached
        /// in a <see cref="TokenCache"/> to be used later (by calls to GetTokenForWebApiAsync).
        /// </summary>
        /// <param name="claimsPrincipal">A <see cref="ClaimsPrincipal"/> for the signed in user</param>
        /// <param name="authorizationCode">a string authorization code obtained when the user signed in</param>
        /// <param name="redirectUri">The Uri of the application requesting the access token</param>
        /// <param name="resource">The resouce identifier of the target resource</param>
        /// <returns>A <see cref="System.Threading.Tasks.Task{Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult}"/>.</returns>
        public async Task<AuthenticationResult> RequestTokenAsync(
            ClaimsPrincipal claimsPrincipal,
            string authorizationCode,
            string redirectUri,
            string resource)
        {
            Guard.ArgumentNotNull(claimsPrincipal, nameof(claimsPrincipal));
            Guard.ArgumentNotNullOrWhiteSpace(authorizationCode, nameof(authorizationCode));
            Guard.ArgumentNotNullOrWhiteSpace(redirectUri, nameof(redirectUri));
            Guard.ArgumentNotNullOrWhiteSpace(resource, nameof(resource));

            try
            {
                var userId = claimsPrincipal.GetObjectIdentifierValue();
                var issuerValue = claimsPrincipal.GetIssuerValue();
                _logger.AuthenticationCodeRedemptionStarted(userId, issuerValue, resource);
                var authenticationContext = await CreateAuthenticationContext(claimsPrincipal)
                    .ConfigureAwait(false);
                var authenticationResult = await authenticationContext.AcquireTokenByAuthorizationCodeAsync(
                    authorizationCode,
                    new Uri(redirectUri),
                    await _credentialService.GetCredentialsAsync().ConfigureAwait(false),
                    resource)
                    .ConfigureAwait(false);

                _logger.AuthenticationCodeRedemptionCompleted(userId, issuerValue, resource);
                return authenticationResult;
            }
            catch (Exception ex)
            {
                _logger.AuthenticationCodeRedemptionFailed(ex);
                throw;
            }
        }