/// <summary>
        /// Get on-behalf-of user access token
        /// </summary>
        /// <param name="userAccessToken">Authenticated client access token taken from request header</param>
        /// <param name="tokenCachingOptions">Token caching options</param>
        /// <returns>Authentication result which contains on behalf of token</returns>
        public async Task <AuthenticationResult> GetAccessTokenFromUserTokenAsync(
            string userAccessToken,
            TokenCachingOptions tokenCachingOptions)
        {
            /* Note: In most cases this won't apply as we don't need this for anything but cases where we recieved a hybrid token.
             * Most of the time we will use "common".
             * We need to read the token and check to see if it has an identity provider claim or IDP.
             * This is needed for instances where apps may use a "hybrid" token where it has app claims and user claims mixed together.
             * This will only happen in instances where a token is generated when the issuer is tenant x but we are requesting a token for an app in tenant y
             * and specifically ask that the authority be tenant y. We do this so that the issuer is listed as tenant y instead of x. When this happens the issuer
             * and tenant in the token can no longer be tenant x so it's moved into IDP. This is needed for validation on the server in instances where
             * we only want another app calling and/or we want to see the user token claims with the app token claims.
             * See here for more details: https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-token-and-claims#access-tokens
             */

            var tenant = this.graphConfig.GraphTenant;

            if (!string.IsNullOrEmpty(userAccessToken))
            {
                var readToken             = (new JwtSecurityTokenHandler()).ReadJwtToken(userAccessToken);
                var identityProviderClaim = readToken.Claims.FirstOrDefault(c => c.Type == IdentityProvider);

                if (identityProviderClaim != null)
                {
                    var tenantMatch = (new Regex(@"https:\/\/sts\.windows\.net\/([0-9A-Za-z-.]*)\/?")).Match(identityProviderClaim.Value);
                    if (tenantMatch.Success)
                    {
                        tenant = tenantMatch.Groups[1].Value;
                        trace.TraceInformation($"Tenant {tenant} was matched from the identity provider claim and will be used to generate a token instead of common");
                    }
                    else
                    {
                        //trace.TraceWarning($"Identity provider claim {identityProviderClaim} was provided but was not matched");
                    }
                }
            }

            return(await this.GetAccessTokenForResourceFromUserTokenAsync(userAccessToken, tenant, this.graphConfig.GraphResourceId, tokenCachingOptions));
        }
Exemplo n.º 2
0
        private static async Task <AuthenticationHeaderValue> GetBearerTokenFromUserToken(string userAccessToken, TokenCachingOptions tokenCachingOptions = TokenCachingOptions.PreferCache)
        {
            if (userAccessToken.ToLower().StartsWith("bearer "))
            {
                userAccessToken = userAccessToken.Remove(0, 7);
            }

            // var resourceToken = await graphProvider.GetResourceAccessTokenFromUserToken(userAccessToken, tokenCachingOptions);

            //  return await GetAuthenticationHeaderValueAsync();

            return(new AuthenticationHeaderValue("Bearer", await GetGraphToken()));
        }
        /// <summary>
        /// Gets an Access token for the given resource on behalf of the user in the provided access token
        /// </summary>
        /// <param name="userAccessToken">The access token</param>
        /// <param name="tenantId">Tenant ID</param>
        /// <param name="resource">Resource ID</param>
        /// <param name="tokenCachingOptions">Token caching options</param>
        /// <returns>Authentication result which contains on behalf of token</returns>
        public async Task <AuthenticationResult> GetAccessTokenForResourceFromUserTokenAsync(
            string userAccessToken,
            string tenantId,
            string resource,
            TokenCachingOptions tokenCachingOptions)
        {
            trace.TraceInformation("Start GetAccessTokenForResourceFromUserTokenAsync");
            var aadInstance             = GetAADInstance(this.aadClientConfig.AADInstance, tenantId);
            var exceptions              = new List <Exception>();
            var thumbprints             = this.aadClientConfig.ClientCertificateThumbprintList;
            var userName                = this.GetUserName();
            AuthenticationResult result = null;

            try
            {
                if (tokenCachingOptions == TokenCachingOptions.PreferCache &&
                    this.TryGetAccessToken(resource, tenantId, userName, out result))
                {
                    trace.TraceInformation("Retrieved access token from cache.");
                    return(result);
                }

                foreach (var thumbprint in thumbprints)
                {
                    try
                    {
                        // Construct context
                        var authority = this.aadClientConfig.AADInstance.FormatWithInvariantCulture(tenantId);
                        var context   = new AuthenticationContext(authority, false);
                        context.CorrelationId = new Guid();

                        // Construct client assertion certificate
                        var certificate = this.certificateManager.FindByThumbprint(thumbprint, StoreName.My, StoreLocation.LocalMachine);
                        var clientAssertionCertificate = new ClientAssertionCertificate(this.aadClientConfig.ClientId, certificate);

                        // User Assertion
                        if (string.IsNullOrEmpty(userAccessToken))
                        {
                            trace.TraceInformation("Calling AcquireTokenAsync without User Assertion.");
                            result = await context.AcquireTokenAsync(resource, clientAssertionCertificate);
                        }
                        else
                        {
                            trace.TraceInformation("Calling AcquireTokenAsync with User Assertion.");
                            var userAssertion = new UserAssertion(TrimBearerToken(userAccessToken));

                            result = await context.AcquireTokenAsync(resource, clientAssertionCertificate, userAssertion);
                        }

                        trace.TraceInformation($"Requesting access token for Resource: '{resource}', AADInstance: '{aadInstance}', ClientID: '{this.aadClientConfig.ClientId}, CorrelationId: '{context.CorrelationId}'");

                        if (!string.IsNullOrEmpty(userName))
                        {
                            // Set Cache
                            this.SetAccessTokenCache(this.graphConfig.GraphResourceId, this.graphConfig.GraphTenant, userName, result);
                        }

                        return(result);
                    }
                    catch (AdalServiceException ex)
                    {
                        // trace.TraceWarning($"AdalServiceException: error code- {ex.ErrorCode}, error message- {ex.Message}");
                        exceptions.Add(ex);
                        //}
                        //catch (CertificateNotFoundException ex)
                        //{
                        //    exceptions.Add(ex);
                    }
                    catch (Exception ex)
                    {
                        exceptions.Add(ex);
                        break;
                    }
                }
            }
            catch (AdalException exception)
            {
                HandleAzureActiveDirectoryClientException(exception);
                return(null);
            }

            throw new AggregateException($"Could not successfully acquire certificate using thumbprints: {string.Join(", ", aadClientConfig.ClientCertificateThumbprintList)}", exceptions);
        }
Exemplo n.º 4
0
            public async Task <string> GetResourceAccessTokenFromUserToken(string token, TokenCachingOptions tokenCachingOptions = TokenCachingOptions.PreferCache)
            {
                var result = await this.azureActiveDirectoryClient.GetAccessTokenFromUserTokenAsync(
                    token,
                    tokenCachingOptions);

                return(result.AccessToken);
            }