Esempio n. 1
0
        /// <summary>
        /// Checks the given HTTP request headers for a valid OpenID Connect (OIDC) Authorization token.
        /// </summary>
        /// <param name="httpRequestHeaders">
        /// The HTTP request headers to check.
        /// </param>
        /// <returns>
        /// Informatoin about the success or failure of the authorization.
        /// </returns>
        public async Task <ApiAuthorizationResult> AuthorizeAsync(
            IHeaderDictionary httpRequestHeaders)
        {
            string authorizationBearerToken = _authorizationHeaderBearerTokenExractor.GetToken(
                httpRequestHeaders);

            if (authorizationBearerToken == null)
            {
                return(new ApiAuthorizationResult(
                           "Authorization header is missing, invalid format, or is not a Bearer token."));
            }

            bool isTokenValid = false;

            int validationRetryCount = 0;

            do
            {
                IEnumerable <SecurityKey> issuerSigningKeys;
                try
                {
                    // Get the cached signing keys if they were retrieved previously.
                    // If they haven't been retrieved, or the cached keys are stale,
                    // then a fresh set of signing keys are retrieved from the OpenID Connect provider
                    // (issuer) cached and returned.
                    // This method will throw if the configuration cannot be retrieved, instead of returning null.
                    issuerSigningKeys = await _oidcConfigurationManager.GetIssuerSigningKeysAsync();
                }
                catch (Exception ex)
                {
                    return(new ApiAuthorizationResult(
                               "Problem getting signing keys from Open ID Connect provider (issuer)."
                               + $" ConfigurationManager threw {ex.GetType()} Message: {ex.Message}"));
                }

                try
                {
                    // Try to validate the token.

                    var tokenValidationParameters = new TokenValidationParameters
                    {
                        RequireSignedTokens      = true,
                        ValidAudience            = _audience,
                        ValidateAudience         = true,
                        ValidIssuer              = _issuerUrl,
                        ValidateIssuer           = true,
                        ValidateIssuerSigningKey = true,
                        ValidateLifetime         = true,
                        IssuerSigningKeys        = issuerSigningKeys
                    };

                    try
                    {
                        // Throws if the the token cannot be validated.
                        _jwtSecurityTokenHandlerWrapper.ValidateToken(
                            authorizationBearerToken,
                            tokenValidationParameters);

                        isTokenValid = true;
                    }
                    catch (SecurityTokenSignatureKeyNotFoundException)
                    {
                        // A SecurityTokenSignatureKeyNotFoundException is thrown if the signing keys for
                        // validating the JWT could not be found. This could happen if the issuer has
                        // changed the signing keys since the last time they were retrieved by the
                        // ConfigurationManager.
                        if (validationRetryCount == 0)
                        {
                            // To handle the SecurityTokenSignatureKeyNotFoundException we ask the
                            // ConfigurationManger to refresh which will cause it to retrieve the keys again
                            // the next time we ask for them.
                            // Then we retry by asking for the signing keys and validating the token again.
                            // We only retry once.
                            _oidcConfigurationManager.RequestRefresh();
                            validationRetryCount++;
                        }
                        else
                        {
                            // We've already re-tried after the first SecurityTokenSignatureKeyNotFoundException,
                            // and we caught the exception again.
                            // This time we rethrow the exception so that we will fail the authorization.
                            throw;
                        }
                    }
                }
                catch (Exception ex)
                {
                    return(new ApiAuthorizationResult(
                               $"Authorization Failed. {ex.GetType()} caught while validating JWT token."
                               + $"Message: {ex.Message}"));
                }
            } while (!isTokenValid);

            // Success result.
            return(new ApiAuthorizationResult());
        }