// this is how you get tokens obtained by the OIDC middleware
        //private Task<string> GetAccessTokenAsync()
        //{
        //    return httpContextAccessor.HttpContext.GetTokenAsync("access_token");
        //}

        // this is how you get tokens with MSAL
        private async Task <string> GetAccessTokenAsync()
        {
            try
            {
                var principal = httpContextAccessor.HttpContext.User;

                var tokenCache = new DistributedTokenCache(distributedCache, principal.FindFirst(Constants.ObjectIdClaimType).Value).GetMSALCache();
                var client     = new ConfidentialClientApplication(authOptions.ClientId,
                                                                   authOptions.GetAuthority(principal.FindFirst(Constants.AcrClaimType).Value),
                                                                   "https://app", // it's not really needed
                                                                   new ClientCredential(authOptions.ClientSecret),
                                                                   tokenCache,
                                                                   null);

                var account = (await client.GetAccountsAsync()).FirstOrDefault();

                var result = await client.AcquireTokenSilentAsync(new[] { $"{authOptions.ApiIdentifier}/read_values" },
                                                                  account);

                return(result.IdToken);
            }
            catch (MsalUiRequiredException)
            {
                throw new ReauthenticationRequiredException();
            }
        }
        public async Task AuthenticateRequestAsync(HttpRequestMessage request)
        {
            var httpContext = _httpContextAccessor.HttpContext;

            //Get the access token used to call this API
            string token = await httpContext.GetTokenAsync("access_token");

            //We are passing an *assertion* to Azure AD about the current user
            //Here we specify that assertion's type, that is a JWT Bearer token
            string assertionType = "urn:ietf:params:oauth:grant-type:jwt-bearer";

            //User name is needed here only for ADAL, it is not passed to AAD
            //ADAL uses it to find a token in the cache if available
            var    user     = httpContext.User;
            string userName = user.FindFirstValue(ClaimTypes.Upn) ?? user.FindFirstValue(ClaimTypes.Email);
            //_logger.LogInformation("UPN: " + user.FindFirstValue(ClaimTypes.Upn) + ", Email: " + user.FindFirstValue(ClaimTypes.Email));

            var userAssertion = new UserAssertion(token, assertionType, userName);

            //Construct the token cache
            var cache = new DistributedTokenCache(user, _distributedCache, _loggerFactory, _dataProtectionProvider);

            var authContext      = new AuthenticationContext(_authority, true, cache);
            var clientCredential = new ClientCredential(_clientId, _clientSecret);

            //Acquire access token
            var result = await authContext.AcquireTokenAsync("https://graph.microsoft.com", clientCredential, userAssertion);

            //Set the authentication header
            request.Headers.Authorization = new AuthenticationHeaderValue(result.AccessTokenType, result.AccessToken);
        }
        /// <summary>
        /// Gets an access token from the authority using app only authentication.
        /// </summary>
        /// <param name="authority">Address of the authority to issue the token.</param>
        /// <param name="resource">Identifier of the target resource that is the recipient of the requested token.</param>
        /// <returns>An instance of <see cref="AuthenticationToken"/> that represented the access token.</returns>
        /// <exception cref="ArgumentException">
        /// <paramref name="authority"/> is empty or null.
        /// or
        /// <paramref name="resource"/> is empty or null.
        /// </exception>
        public async Task <AuthenticationResult> GetAppOnlyTokenAsync(string authority, string resource)
        {
            AuthenticationContext authContext;
            DistributedTokenCache tokenCache;

            authority.AssertNotEmpty(nameof(authority));
            resource.AssertNotEmpty(nameof(resource));

            try
            {
                if (service.Cache.IsEnabled)
                {
                    tokenCache  = new DistributedTokenCache(service, resource, $"AppOnly::{resource}");
                    authContext = new AuthenticationContext(authority, tokenCache);
                }
                else
                {
                    authContext = new AuthenticationContext(authority);
                }

                return(await authContext.AcquireTokenAsync(
                           resource,
                           new ClientCredential(
                               service.Configuration.ApplicationId,
                               service.Configuration.ApplicationSecret)));
            }
            finally
            {
                authContext = null;
                tokenCache  = null;
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Gets an access token from the authority using app + user authentication.
        /// </summary>
        /// <param name="authority">Address of the authority to issue the token.</param>
        /// <param name="resource">Identifier of the target resource that is the recipient of the requested token.</param>
        /// <returns>An instance of <see cref="AuthenticationToken"/> that represented the access token.</returns>
        /// <exception cref="ArgumentException">
        /// <paramref name="authority"/> is empty or null.
        /// or
        /// <paramref name="resource"/> is empty or null.
        /// </exception>
        public async Task <AuthenticationToken> GetAppPlusUserTokenAsync(string authority, string resource)
        {
            AuthenticationContext authContext;
            AuthenticationResult  authResult;
            DistributedTokenCache tokenCache;

            authority.AssertNotEmpty(nameof(authority));
            resource.AssertNotEmpty(nameof(resource));

            try
            {
                if (this.service.Cache.IsEnabled)
                {
                    tokenCache  = new DistributedTokenCache(this.service, resource);
                    authContext = new AuthenticationContext(authority, tokenCache);
                }
                else
                {
                    authContext = new AuthenticationContext(authority);
                }

                try
                {
                    authResult = await authContext.AcquireTokenAsync(
                        resource,
                        new ClientCredential(
                            this.service.Configuration.ApplicationId,
                            this.service.Configuration.ApplicationSecret),
                        new UserAssertion(UserAssertionToken, AssertionType));
                }
                catch (AdalServiceException ex)
                {
                    if (ex.ErrorCode.Equals("AADSTS70002", StringComparison.CurrentCultureIgnoreCase))
                    {
                        await this.service.Cache.DeleteAsync(CacheDatabaseType.Authentication);

                        authResult = await authContext.AcquireTokenAsync(
                            resource,
                            new ClientCredential(
                                this.service.Configuration.ApplicationId,
                                this.service.Configuration.ApplicationSecret),
                            new UserAssertion(UserAssertionToken, AssertionType));
                    }
                    else
                    {
                        throw;
                    }
                }

                return(new AuthenticationToken(authResult.AccessToken, authResult.ExpiresOn));
            }
            finally
            {
                authContext = null;
                authResult  = null;
                tokenCache  = null;
            }
        }
Esempio n. 5
0
        private static OpenIdConnectEvents CreateOpenIdConnectEventHandlers(B2CAuthenticationOptions authOptions, B2CPolicies policies, IDistributedCache distributedCache)
        {
            return(new OpenIdConnectEvents
            {
                OnRedirectToIdentityProvider = context => SetIssuerAddressAsync(context, policies.SignInOrSignUpPolicy),
                OnRedirectToIdentityProviderForSignOut = context => SetIssuerAddressForSignOutAsync(context, policies.SignInOrSignUpPolicy),
                OnAuthorizationCodeReceived = async context =>
                {
                    try
                    {
                        var principal = context.Principal;

                        var userTokenCache = new DistributedTokenCache(distributedCache, principal.FindFirst(Constants.ObjectIdClaimType).Value).GetMSALCache();
                        var client = new ConfidentialClientApplication(authOptions.ClientId,
                                                                       authOptions.GetAuthority(principal.FindFirst(Constants.AcrClaimType).Value),
                                                                       "https://app", // it's not really needed
                                                                       new ClientCredential(authOptions.ClientSecret),
                                                                       userTokenCache,
                                                                       null);

                        var result = await client.AcquireTokenByAuthorizationCodeAsync(context.TokenEndpointRequest.Code,
                                                                                       new[] { $"{authOptions.ApiIdentifier}/read_values" });

                        context.HandleCodeRedemption(result.AccessToken, result.IdToken);
                    }
                    catch (Exception ex)
                    {
                        context.Fail(ex);
                    }
                },
                OnAuthenticationFailed = context =>
                {
                    context.Fail(context.Exception);
                    return Task.FromResult(0);
                },
                OnMessageReceived = context =>
                {
                    if (!string.IsNullOrEmpty(context.ProtocolMessage.Error) &&
                        !string.IsNullOrEmpty(context.ProtocolMessage.ErrorDescription))
                    {
                        if (context.ProtocolMessage.ErrorDescription.StartsWith("AADB2C90091")) // cancel profile editing
                        {
                            context.HandleResponse();
                            context.Response.Redirect("/");
                        }
                        else if (context.ProtocolMessage.ErrorDescription.StartsWith("AADB2C90118")) // forgot password
                        {
                            context.HandleResponse();
                            context.Response.Redirect("/Account/ResetPassword");
                        }
                    }

                    return Task.FromResult(0);
                }
            });
        }
        /// <summary>
        /// Gets an access token from the authority.
        /// </summary>
        /// <param name="authority">Address of the authority to issue the token.</param>
        /// <param name="resource">Identifier of the target resource that is the recipent of the requested token.</param>
        /// <param name="thumbprint">Thumbprint for the certificate to be used for authentication.</param>
        /// <returns>An instance of <see cref="AuthenticationResult"/> that represents the access token.</returns>
        /// <remarks>
        /// See https://github.com/Azure/azure-content/blob/master/articles/key-vault/key-vault-use-from-web-application.md
        /// for additional details regarding using this approach for obtaining an access token.
        /// </remarks>
        public async Task <AuthenticationResult> GetAppOnlyTokenAsync(string authority, string resource, string thumbprint)
        {
            AuthenticationContext authContext;
            DistributedTokenCache tokenCache;

            if (string.IsNullOrEmpty(authority))
            {
                throw new ArgumentNullException(nameof(authority));
            }
            if (string.IsNullOrEmpty(resource))
            {
                throw new ArgumentNullException(nameof(resource));
            }
            if (string.IsNullOrEmpty(thumbprint))
            {
                throw new ArgumentNullException(thumbprint);
            }

            try
            {
                // If the Redis Cache connection string is not populated then utilize the constructor
                // that only requires the authority. That constructor will utilize a in-memory caching
                // feature that is built-in into ADAL.
                if (string.IsNullOrEmpty(Settings.RedisConnection))
                {
                    authContext = new AuthenticationContext(authority);
                }
                else
                {
                    tokenCache  = new DistributedTokenCache(resource);
                    authContext = new AuthenticationContext(authority, tokenCache);
                }

                return(await authContext.AcquireTokenAsync(
                           resource,
                           new ClientAssertionCertificate(
                               Settings.ApplicationId,
                               FindCertificateByThumbprint(thumbprint))));
            }
            finally
            {
                authContext = null;
                tokenCache  = null;
            }
        }
        /// <summary>
        /// Gets an access token from the authority.
        /// </summary>
        /// <param name="authority">Address of the authority to issue the token.</param>
        /// <param name="resource">Identifier of the target resource that is the recipient of the requested token.</param>
        /// <param name="credential">The application credential to use for token acquisition.</param>
        /// <param name="token">Assertion token representing the user.</param>
        /// <returns>An instance of <see cref="AuthenticationResult"/> that represented the access token.</returns>
        /// <exception cref="System.ArgumentException">
        /// <paramref name="authority"/> is empty or null.
        /// or
        /// <paramref name="resource"/> is empty or null.
        /// or
        /// <paramref name="token"/> is empty or null.
        /// </exception>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="credential"/> is null.
        /// </exception>
        public async Task <AuthenticationResult> GetAccessTokenAsync(string authority, string resource, ApplicationCredential credential, string token)
        {
            AuthenticationContext authContext;
            AuthenticationResult  authResult;
            DistributedTokenCache tokenCache;
            ISecureClientSecret   secret;

            authority.AssertNotEmpty(nameof(authority));
            resource.AssertNotEmpty(nameof(authority));
            credential.AssertNotNull(nameof(credential));
            token.AssertNotEmpty(nameof(token));

            try
            {
                if (credential.UseCache)
                {
                    tokenCache  = new DistributedTokenCache(provider, resource);
                    authContext = new AuthenticationContext(authority, tokenCache);
                }
                else
                {
                    authContext = new AuthenticationContext(authority);
                }

                secret = new SecureClientSecret(credential.ApplicationSecret);

                authResult = await authContext.AcquireTokenAsync(
                    resource,
                    new ClientCredential(
                        credential.ApplicationId,
                        secret),
                    new UserAssertion(token, AssertionType)).ConfigureAwait(false);

                return(authResult);
            }
            finally
            {
                authContext = null;
                tokenCache  = null;
                secret      = null;
            }
        }
        /// <summary>
        /// Gets an access token from the authority.
        /// </summary>
        /// <param name="authority">Address of the authority to issue the token.</param>
        /// <param name="resource">Identifier of the target resource that is the recipient of the requested token.</param>
        /// <param name="credential">The application credential to use for token acquisition.</param>
        /// <returns>An instance of <see cref="AuthenticationResult"/> that represented the access token.</returns>
        /// <exception cref="System.ArgumentException">
        /// <paramref name="authority"/> is empty or null.
        /// or
        /// <paramref name="resource"/> is empty or null.
        /// </exception>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="credential"/> is null.
        /// </exception>
        public async Task <AuthenticationResult> GetAccessTokenAsync(string authority, string resource, ApplicationCredential credential)
        {
            AuthenticationContext authContext;
            AuthenticationResult  authResult;
            DistributedTokenCache tokenCache;

            Microsoft.IdentityModel.Clients.ActiveDirectory.ISecureClientSecret secret;

            authority.AssertNotEmpty(nameof(authority));
            resource.AssertNotEmpty(nameof(resource));
            credential.AssertNotNull(nameof(credential));

            try
            {
                if (credential.UseCache)
                {
                    tokenCache  = new DistributedTokenCache(provider, resource, $"AppOnly::{authority}::{resource}");
                    authContext = new AuthenticationContext(authority, tokenCache);
                }
                else
                {
                    authContext = new AuthenticationContext(authority);
                }

                secret = new SecureClientSecret(credential.ApplicationSecret);

                authResult = await authContext.AcquireTokenAsync(
                    resource,
                    new ClientCredential(
                        credential.ApplicationId,
                        secret)).ConfigureAwait(false);

                return(authResult);
            }
            finally
            {
                authContext = null;
                authResult  = null;
                secret      = null;
                tokenCache  = null;
            }
        }
        /// <summary>
        /// Gets an access token from the authority.
        /// </summary>
        /// <param name="authority">Address of the authority to issue the token.</param>
        /// <param name="resource">Identifier of the target resource that is the recipent of the requested token.</param>
        /// <returns>An instnace of <see cref="AuthenticationResult"/> that represented the access token.</returns>
        /// <exception cref="ArgumentNullException">
        /// authority
        /// or
        /// resource
        /// </exception>
        public async Task <AuthenticationResult> GetAppPlusUserTokenAsync(string authority, string resource)
        {
            AuthenticationContext authContext;
            DistributedTokenCache tokenCache;

            if (string.IsNullOrEmpty(authority))
            {
                throw new ArgumentNullException(nameof(authority));
            }
            if (string.IsNullOrEmpty(resource))
            {
                throw new ArgumentNullException(nameof(resource));
            }

            try
            {
                // If the Redis Cache connection string is not populated then utilize the constructor
                // that only requires the authority. That constructor will utilize a in-memory caching
                // feature that is built-in into ADAL.
                if (string.IsNullOrEmpty(Settings.RedisConnection))
                {
                    authContext = new AuthenticationContext(authority);
                }
                else
                {
                    tokenCache  = new DistributedTokenCache(resource);
                    authContext = new AuthenticationContext(authority, tokenCache);
                }

                return(await authContext.AcquireTokenAsync(
                           resource,
                           new ClientCredential(
                               Settings.ApplicationId,
                               Settings.ApplicationSecret),
                           new UserAssertion(UserAssertionToken, "urn:ietf:params:oauth:grant-type:jwt-bearer")));
            }
            finally
            {
                authContext = null;
                tokenCache  = null;
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Asynchronously obtains an Azure AD token for the specified resource.
        /// </summary>
        /// <param name="authority">Authority used to obtain the token.</param>
        /// <param name="resource">Identifier of the target resource that is the recipient of the requested token.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">
        /// authority
        /// or
        /// resource
        /// </exception>
        /// <remarks>This function obtains a token for the specified resource on behalf the current authenticated user.</remarks>
        public static async Task <AuthenticationResult> GetAADTokenAsync(string authority, string resource)
        {
            AuthenticationContext authContext;
            DistributedTokenCache tokenCache;

            if (string.IsNullOrEmpty(authority))
            {
                throw new ArgumentNullException(nameof(authority));
            }
            if (string.IsNullOrEmpty(resource))
            {
                throw new ArgumentNullException(nameof(resource));
            }

            try
            {
                if (string.IsNullOrEmpty(AppConfig.RedisConnection))
                {
                    authContext = new AuthenticationContext(authority);
                }
                else
                {
                    tokenCache  = new DistributedTokenCache(resource);
                    authContext = new AuthenticationContext(authority, tokenCache);
                }

                return(await authContext.AcquireTokenAsync(
                           resource,
                           new ClientCredential(
                               AppConfig.ApplicationId,
                               AppConfig.ApplicationSecret),
                           new UserAssertion(UserAssertionToken, "urn:ietf:params:oauth:grant-type:jwt-bearer")));
            }
            finally
            {
                authContext = null;
                tokenCache  = null;
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Gets an access token utilizing an authorization code.
        /// </summary>
        /// <param name="authority">Address of the authority to issue the token.</param>
        /// <param name="code">Authorization code received from the service authorization endpoint.</param>
        /// <param name="resource">Identifier of the target resource that is the recipient of the requested token.</param>
        /// <param name="redirectUri">Redirect URI used for obtain the authorization code.</param>
        /// <returns>An instance of <see cref="AuthenticationToken"/> that represented the access token.</returns>
        /// <exception cref="ArgumentException">
        /// authority
        /// or
        /// code
        /// or
        /// resource
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// redirectUri
        /// </exception>
        public async Task <AuthenticationToken> GetTokenByAuthorizationCodeAsync(string authority, string code, string resource, Uri redirectUri)
        {
            AuthenticationContext authContext;
            AuthenticationResult  authResult;
            DistributedTokenCache tokenCache;

            authority.AssertNotEmpty(nameof(authority));
            code.AssertNotEmpty(nameof(code));
            redirectUri.AssertNotNull(nameof(redirectUri));
            resource.AssertNotEmpty(nameof(resource));

            try
            {
                if (this.service.Cache.IsEnabled)
                {
                    tokenCache  = new DistributedTokenCache(this.service, resource);
                    authContext = new AuthenticationContext(authority, tokenCache);
                }
                else
                {
                    authContext = new AuthenticationContext(authority);
                }

                authResult = await authContext.AcquireTokenByAuthorizationCodeAsync(
                    code,
                    redirectUri,
                    new ClientCredential(
                        this.service.Configuration.ApplicationId,
                        this.service.Configuration.ApplicationSecret),
                    resource);

                return(new AuthenticationToken(authResult.AccessToken, authResult.ExpiresOn));
            }
            finally
            {
                authContext = null;
                tokenCache  = null;
            }
        }
Esempio n. 12
0
        public ActionResult Logout()
        {
            string userObjectId = User.GetObjectIdentifierValue();

            //Get an instance of the token cache for the current user request
            IDistributedCache distributedCache = HttpContext.RequestServices.GetRequiredService <IDistributedCache>();

            var cache = new DistributedTokenCache(User, distributedCache);
            AuthenticationContext authContext = new AuthenticationContext(Startup._authority, cache);

            authContext.TokenCache.Clear();

            //Explicitly delete the cookie(this is an IE compatability thing)
            Response.Cookies.Delete("thing_faceter_AUTH");

            // Let Azure AD sign-out
            return(SignOut(
                       new AuthenticationProperties {
                RedirectUri = _environmentOptions.Post_Logout_Redirect_Uri
            },
                       CookieAuthenticationDefaults.AuthenticationScheme,
                       OpenIdConnectDefaults.AuthenticationScheme
                       ));
        }