예제 #1
0
        protected InstanceAuthorizationResult AuthorizeInstance(
            EdFiAuthorizationContext authorizationContext,
            AuthorizationFilterContext filterContext)
        {
            if (filterContext.SubjectEndpointValue == null)
            {
                // This should never happen
                throw new EdFiSecurityException(
                          $"Access to the resource item could not be authorized because the '{filterContext.SubjectEndpointName}' of the resource is empty.");
            }

            // If the subject's endpoint name is an Education Organization Id, we can try to authenticate it here.
            if (_educationOrganizationIdNamesProvider.IsEducationOrganizationIdName(filterContext.SubjectEndpointName))
            {
                // NOTE: Could consider caching the EdOrgToEdOrgId tuple table.
                // If the EdOrgId values match, then we can report the filter as successfully authorized
                if (_apiKeyContextProvider.GetApiKeyContext()
                    .EducationOrganizationIds.Contains((int)filterContext.SubjectEndpointValue))
                {
                    return(InstanceAuthorizationResult.Success());
                }
            }

            return(InstanceAuthorizationResult.NotPerformed());
        }
예제 #2
0
        public async Task <IHttpActionResult> PostAsync([FromBody] TokenInfoRequest tokenInfoRequest)
        {
            // see https://tools.ietf.org/html/rfc7662#section-2.2 for oauth token_info spec
            if (tokenInfoRequest == null || tokenInfoRequest.Token == null ||
                !Guid.TryParse(tokenInfoRequest.Token, out Guid accessToken))
            {
                return(BadRequest("Invalid token"));
            }

            var oAuthTokenClient = (await _tokenClientRepo.GetClientForTokenAsync(accessToken)).FirstOrDefault();

            if (oAuthTokenClient == null)
            {
                return(NotFound());
            }

            ApiKeyContext apiContext = _apiKeyContextProvider.GetApiKeyContext();

            // must be able to see my specific items ie vendor a cannot look at vendor b
            if (oAuthTokenClient.Key != apiContext.ApiKey)
            {
                return(Unauthorized());
            }

            TokenInfo tokenInfo = await _tokenInfoProvider.GetTokenInfoAsync(apiContext);

            HttpContext.Current.Response.Headers.Add("Cache-Control", "no-cache");
            return(Ok(tokenInfo));
        }
        public async Task CreateAsync(T entity, bool enforceOptimisticLock, CancellationToken cancellationToken)
        {
            Preconditions.ThrowIfNull(entity, nameof(entity));

            // POST comes in as an "Upsert", but at this point we know it's actually about to create an entity,
            // so we'll use the more explicit action for authorization.
            short?creatorOwnershipTokenId = _apiKeyContextProvider.GetApiKeyContext().CreatorOwnershipTokenId;

            entity.CreatedByOwnershipTokenId = creatorOwnershipTokenId;

            // Pass the call through to the decorated repository method
            await _next.CreateAsync(entity, enforceOptimisticLock, cancellationToken);
        }
        public string GetReplacementToken()
        {
            //Convention: "Ods_Sandbox_" + vendor's api key.
            string apiKey = apiKeyContextProvider.GetApiKeyContext()
                            .ApiKey;

            if (string.IsNullOrEmpty(apiKey))
            {
                throw new InvalidOperationException(
                          "The sandbox ODS database name replacement token cannot be derived because the API key was not set in the current context.");
            }

            return(string.Format("Ods_Sandbox_{0}", apiKey));
        }
        public async Task <IActionResult> Get([FromRoute(Name = "uniqueId")] string uniqueId)
        {
            try
            {
                if (uniqueId.Length != 10 || !long.TryParse(uniqueId, out _))
                {
                    return(StatusCode((int)HttpStatusCode.BadRequest, new { Message = "The UniqueId was not valid." }));
                }

                var localEducationOrganizationIds = _apiKeyContextProvider.GetApiKeyContext().EducationOrganizationIds.ToArray();

                var wirSchools = _immunizationsWirSchoolProvider.GetWirSchools(localEducationOrganizationIds);
                if (!wirSchools.Any())
                {
                    return(StatusCode((int)HttpStatusCode.ServiceUnavailable,
                                      new { Message = "DHS school code missing, immunization service unavailable. Submit a ticket to DPI Customer Service with questions https://dpi.wi.gov/wisedash/help/ticket" }));
                }

                var patient = _immunizationsPatientIdentificationProvider.GetPatientIdentification(uniqueId, localEducationOrganizationIds);

                if (!patient.StudentExists || !patient.SsaExists)
                {
                    return(StatusCode((int)HttpStatusCode.Forbidden, new { Message = $"The student does not exist or this ApiKey is not Authorized to access the student" }));
                }

                var request  = _immunizationsRequestProvider.GetImmunizationsRequest(patient);
                var response = await _immunizationsWirClient.RequestImmunizationsAsync(request);

                var result = _immunizationsResponseProvider.GetImmunizationsResponse(response, patient);

                if (result.Errors != null && result.Errors.Any())
                {
                    var errors = string.Join(",", result.Errors.Select(e => e.Error));
                    Logger.Error($"ImmunizationsStudentsController GET WiR Error(s): {errors}");
                    var errorMessage = string.Join(",", result.Errors.Select(e => e.ErrorMessage));
                    result.Errors = null;
                    return(StatusCode((int)HttpStatusCode.BadGateway, new { Message = $"The student immunization records cannot be retrieved because of a WIR error. Please login to the WIR to resolve the issue or contact DPI to help investigate. The error message WIR returned was {errorMessage}" }));
                }
                result.Errors = null;

                return(Ok(result));
            }
            catch (Exception exception)
            {
                Logger.Error("ImmunizationsStudentsController GET FaultException", exception);
                return(StatusCode((int)HttpStatusCode.ServiceUnavailable, new { Message = $"There was a FaultException connecting to DHS WiR: {exception}" }));
            }
        }
예제 #6
0
        public ClaimsIdentity GetClaimsIdentity()
        {
            // Get the Education Organization Ids for the current context
            var apiKeyContext = _apiKeyContextProvider.GetApiKeyContext();

            if (apiKeyContext == null || apiKeyContext == ApiKeyContext.Empty)
            {
                throw new EdFiSecurityException("No API key information was available for authorization.");
            }

            return(GetClaimsIdentity(
                       apiKeyContext.EducationOrganizationIds,
                       apiKeyContext.ClaimSetName,
                       apiKeyContext.NamespacePrefixes,
                       apiKeyContext.Profiles.ToList()));
        }
        public string GetReplacementToken()
        {
            List <int> availableEducationOrganizations = _apiKeyContextProvider.GetApiKeyContext()?.EducationOrganizationIds?.ToList() ??
                                                         new List <int>();

            if (!availableEducationOrganizations.Any())
            {
                throw new InvalidOperationException(
                          "The district-specific ODS database name replacement token cannot be derived because no available education organizations were found in the current context. Ensure the api client is correctly configured for exactly one local education agency to use this token provider.");
            }
            else if (availableEducationOrganizations.Count > 1)
            {
                throw new InvalidOperationException(
                          "The district-specific ODS database name replacement token cannot be derived because more than one available education organization was found in the current context. Ensure the api client is correctly configured for exactly one local education agency to use this token provider.");
            }

            //Convention: "Ods_" + local education agency id
            return($"Ods_{availableEducationOrganizations.Single()}");
        }
예제 #8
0
        private async Task <IActionResult> GetTokenInformation(TokenInfoRequest tokenInfoRequest)
        {
            if (!_isEnabled)
            {
                return(NotFound());
            }

            // see https://tools.ietf.org/html/rfc7662#section-2.2 for oauth token_info spec
            if (tokenInfoRequest == null || tokenInfoRequest.Token == null ||
                !Guid.TryParse(tokenInfoRequest.Token, out Guid accessToken))
            {
                return(BadRequest(ErrorTranslator.GetErrorMessage("Invalid token")));
            }

            var oAuthTokenClient = (await _tokenClientRepo.GetClientForTokenAsync(accessToken)).FirstOrDefault();

            if (oAuthTokenClient == null)
            {
                return(NotFound());
            }

            ApiKeyContext apiContext = _apiKeyContextProvider.GetApiKeyContext();

            // must be able to see my specific items ie vendor a cannot look at vendor b
            if (oAuthTokenClient.Key != apiContext.ApiKey)
            {
                return(Unauthorized());
            }

            var tokenInfo = await _tokenInfoProvider.GetTokenInfoAsync(apiContext);

            Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue {
                NoCache = true
            };
            return(Ok(tokenInfo));
        }
예제 #9
0
            protected override void Arrange()
            {
                // Initialize dependencies

                const string suppliedClaimSetName = "claimSetName";

                var apiKeyContext = new ApiKeyContext(
                    "apiKey",
                    suppliedClaimSetName,
                    _suppliedEducationOrganizationIds,
                    _suppliedNamespacePrefixes,
                    _suppliedProfiles,
                    null, null, null);

                _apiKeyContextProvider = A.Fake <IApiKeyContextProvider>();
                A.CallTo(() => _apiKeyContextProvider.GetApiKeyContext()).Returns(apiKeyContext);

                var suppliedResourceClaims = new List <ClaimSetResourceClaimAction>
                {
                    new ClaimSetResourceClaimAction
                    {
                        Action = new Action {
                            ActionUri = "actionUri-1a"
                        },
                        ResourceClaim = new ResourceClaim {
                            ClaimName = "resourceClaimName1"
                        },
                        AuthorizationStrategyOverrides = new List <ClaimSetResourceClaimActionAuthorizationStrategyOverrides>
                        {
                            new ClaimSetResourceClaimActionAuthorizationStrategyOverrides
                            {
                                AuthorizationStrategy = new AuthorizationStrategy {
                                    AuthorizationStrategyName = "actionUri-1a-Strategy"
                                }
                            }
                        },
                        ValidationRuleSetNameOverride = null
                    },
                    new ClaimSetResourceClaimAction
                    {
                        Action = new Action {
                            ActionUri = "actionUri-1b"
                        },
                        ResourceClaim = new ResourceClaim {
                            ClaimName = "resourceClaimName1"
                        },
                        AuthorizationStrategyOverrides = new List <ClaimSetResourceClaimActionAuthorizationStrategyOverrides>
                        {
                            new ClaimSetResourceClaimActionAuthorizationStrategyOverrides
                            {
                                AuthorizationStrategy = new AuthorizationStrategy {
                                    AuthorizationStrategyName = "actionUri-1b-Strategy"
                                }
                            }
                        },
                        ValidationRuleSetNameOverride = "actionUri-1b-RuleSetName"
                    },
                    new ClaimSetResourceClaimAction
                    {
                        Action = new Action {
                            ActionUri = "actionUri-2"
                        },
                        ResourceClaim = new ResourceClaim {
                            ClaimName = "resourceClaimName2"
                        },
                        AuthorizationStrategyOverrides = null,
                        ValidationRuleSetNameOverride  = "actionUri-2-RuleSetName"
                    }
                };

                _securityRepository = A.Fake <ISecurityRepository>();
                A.CallTo(() => _securityRepository.GetClaimsForClaimSet(suppliedClaimSetName)).Returns(suppliedResourceClaims);
            }
예제 #10
0
        public Task <HttpResponseMessage> ExecuteAuthorizationFilterAsync(
            HttpActionContext actionContext,
            CancellationToken cancellationToken,
            Func <Task <HttpResponseMessage> > continuation)
        {
            // check if the http method sent needs to be checked by this filter
            if (!(actionContext.Request.Method == HttpMethod.Put ||
                  actionContext.Request.Method == HttpMethod.Post ||
                  actionContext.Request.Method == HttpMethod.Get))
            {
                return(continuation());
            }

            // Try to get the current API key context
            var assignedProfiles = new List <string>();
            var apiKeyContext    = _apiKeyContextProvider.GetApiKeyContext();

            // check that the ApiKeyContext is available so that we can get the assigned profiles
            if (apiKeyContext != null && apiKeyContext != ApiKeyContext.Empty)
            {
                assignedProfiles = _apiKeyContextProvider.GetApiKeyContext()
                                   .Profiles.ToList();
            }

            // declare profile content type variable because it can be retrieved from the
            // accept header or the content-type header
            string profileContentType = null;
            ProfileContentTypeDetails profileContentTypeDetails = null;

            // get singluar spelling of the controller name for comparison to the resource in the profiles
            string resourceCollectionName =
                actionContext.ControllerContext.ControllerDescriptor.ControllerName.TrimSuffix("Controller");

            string resourceItemName = CompositeTermInflector.MakeSingular(resourceCollectionName);

            // try to get the Profile Content type and parse if successful
            if (TryGetProfileContentType(actionContext, out profileContentType))
            {
                profileContentTypeDetails = profileContentType.GetContentTypeDetails();
            }

            // If the caller has not specified a profile specific content type and there are no assigned
            // profiles then allow the request to be processed (there is nothing left to check)
            if (string.IsNullOrEmpty(profileContentType) && !assignedProfiles.Any())
            {
                return(continuation());
            }

            // If the caller has not specified a profile specific content type but the targeted
            // resource is covered by an assigned profile then we must refuse the request
            if (string.IsNullOrEmpty(profileContentType) &&
                IsResourceCoveredByAssignedProfile(assignedProfiles, resourceItemName))
            {
                if (actionContext.Request.Method == HttpMethod.Get)
                {
                    return
                        (Task.FromResult(
                             ForbiddenHttpResponseMessage(
                                 actionContext,
                                 string.Format(
                                     "One of the following profile-specific content types is required when requesting this resource: '{0}'.",
                                     string.Join(
                                         "', '",
                                         assignedProfiles.Select(
                                             p => ProfilesContentTypeHelper.CreateContentType(
                                                 resourceCollectionName,
                                                 p,
                                                 ContentTypeUsage.Readable)))))));
                }

                // PUT or POST
                return
                    (Task.FromResult(
                         ForbiddenHttpResponseMessage(
                             actionContext,
                             string.Format(
                                 "Based on the assigned profiles, one of the following profile-specific content types is required when updating this resource: '{0}'.",
                                 string.Join(
                                     "', '",
                                     assignedProfiles.Select(
                                         p => ProfilesContentTypeHelper.CreateContentType(resourceCollectionName, p, ContentTypeUsage.Writable)))))));
            }

            // if there is no profile specific content at this point there are no more checks to make so proceed with request processing
            if (string.IsNullOrEmpty(profileContentType))
            {
                return(continuation());
            }

            // If the caller is "opting in" to a profile, and the targeted resource exists in the specified profile, proceed with request processing
            if (!assignedProfiles.Any() &&
                IsTheResourceInTheProfile(resourceItemName, profileContentTypeDetails.Profile))
            {
                return(continuation());
            }

            // If the caller is not assigned any profiles that cover the targeted resource, then proceed with request processing.
            if (!AnyAssignedProfilesCoverTheResource(assignedProfiles, resourceItemName))
            {
                return(continuation());
            }

            // Check if the resource is covered under an assigned profile that is not the profile content type sent
            if (!IsResourceCoveredByAnotherAssignedProfile(assignedProfiles, resourceItemName, profileContentTypeDetails.Profile))
            {
                // create the response based on the method
                if (actionContext.Request.Method == HttpMethod.Get)
                {
                    return(Task.FromResult(
                               ForbiddenHttpResponseMessage(
                                   actionContext,
                                   string.Format(
                                       "One of the following profile-specific content types is required when requesting this resource: '{0}'.",
                                       string.Join(
                                           "', '",
                                           GetApplicableContentTypes(
                                               assignedProfiles,
                                               resourceCollectionName,
                                               resourceItemName,
                                               actionContext.Request.Method))))));
                }

                if (actionContext.Request.Method == HttpMethod.Put || actionContext.Request.Method == HttpMethod.Post)
                {
                    return(Task.FromResult(
                               ForbiddenHttpResponseMessage(
                                   actionContext,
                                   string.Format(
                                       "Based on the assigned profiles, one of the following profile-specific content types is required when updating this resource: '{0}'.",
                                       string.Join(
                                           "', '",
                                           GetApplicableContentTypes(
                                               assignedProfiles,
                                               resourceCollectionName,
                                               resourceItemName,
                                               actionContext.Request.Method))))));
                }
            }

            return(continuation());
        }
        /// <summary>
        /// Applies processing related to the usage/entry to another top-level resource (e.g. applying authorization concerns).
        /// </summary>
        /// <param name="processorContext">The composite definition processor context.</param>
        /// <param name="builderContext">The current builder context.</param>
        /// <returns><b>true</b> if the resource can be processed; otherwise <b>false</b>.</returns>
        public bool TryIncludeResource(CompositeDefinitionProcessorContext processorContext, HqlBuilderContext builderContext)
        {
            var resourceClass = processorContext.CurrentResourceClass;

            if (!(resourceClass is Resource))
            {
                throw new InvalidOperationException(
                          $"Unable to evaluate resource '{resourceClass.FullName}' for inclusion in HQL query because it is not the root class of the resource.");
            }

            var resource = (Resource)resourceClass;

            // --------------------------
            //   Determine inclusion
            // --------------------------
            var entityType = GetEntityType(resource);

            var authorizationContext = new EdFiAuthorizationContext(
                _apiKeyContextProvider.GetApiKeyContext(),
                ClaimsPrincipal.Current,
                _resourceClaimUriProvider.GetResourceClaimUris(resource),
                RequestActions.ReadActionUri,
                entityType);

            // Authorize and apply filtering
            IReadOnlyList <AuthorizationStrategyFiltering> authorizationFiltering;

            try
            {
                var authorizationBasisMetadata = _authorizationBasisMetadataSelector.SelectAuthorizationBasisMetadata(authorizationContext);

                // NOTE: Possible performance optimization - Allow for "Try" semantics (so no exceptions are thrown here)
                authorizationFiltering = _authorizationFilteringProvider.GetAuthorizationFiltering(authorizationContext, authorizationBasisMetadata);
            }
            catch (EdFiSecurityException ex)
            {
                // If this is the base resource, rethrow the exception to achieve a 401 response
                if (processorContext.IsBaseResource())
                {
                    Logger.Debug($"BaseResource: {processorContext.CurrentResourceClass.Name} could not be authorized.");
                    throw;
                }

                // In the case where we have an abstract class and it has no claim, eg EducationOrganization, we will allow
                // the join if the subtype has been included.
                if (processorContext.IsAbstract())
                {
                    Logger.Debug($"Resource {processorContext.CurrentResourceClass.Name} has no claim.");

                    if (processorContext.ShouldIncludeResourceSubtype())
                    {
                        Logger.Debug(
                            $"Resource is abstract and so target resource '{processorContext.CurrentResourceClass.Name}' cannot be authorized. Join will be included, but non-identifying resource members should be stripped from results.");

                        return(true);
                    }
                }

                Logger.Debug($"Resource {processorContext.CurrentResourceClass.Name} is excluded from the request.");
                Logger.Debug($"Security Exception Message: {ex.Message}.");

                return(false);
            }

            // Save the filters to be applied to this query for use later in the process
            builderContext.CurrentQueryFilterByName = authorizationFiltering
                                                      // Flattens the filters as per legacy code (effectively combining them using "AND" logic), but we still need to implement support for combining multiple authorization strategies correctly
                                                      .SelectMany(x => x.Filters)
                                                      .ToDictionary(x => x.FilterName, x => x);

            return(true);
        }
        /// <summary>
        /// Invokes authorization of the request using the resource currently in context but wit
        /// an override action (e.g. for converting the "Upsert" action to either "Create" or "Update").
        /// </summary>
        /// <param name="entity">The request/entity being authorized.</param>
        /// <param name="actionUri">The action being performed with the request/entity.</param>
        /// <param name="cancellationToken"></param>
        protected async Task AuthorizeSingleItemAsync(TEntity entity, string actionUri, CancellationToken cancellationToken)
        {
            // Make sure Authorization context is present before proceeding
            _authorizationContextProvider.VerifyAuthorizationContextExists();

            // Build the AuthorizationContext
            var authorizationContext = new EdFiAuthorizationContext(
                _apiKeyContextProvider.GetApiKeyContext(),
                ClaimsPrincipal.Current,
                _authorizationContextProvider.GetResourceUris(),
                actionUri,
                entity);

            var authorizationBasisMetadata = _authorizationBasisMetadataSelector.SelectAuthorizationBasisMetadata(authorizationContext);

            ExecuteAuthorizationValidationRules(authorizationContext, authorizationBasisMetadata);

            // Get the authorization filtering information
            var authorizationFiltering =
                _authorizationFilteringProvider.GetAuthorizationFiltering(authorizationContext, authorizationBasisMetadata);

            var andResults = PerformInstanceBasedAuthorization(authorizationFiltering, authorizationContext, FilterOperator.And);

            // If any failures occurred with the AND strategies, throw the first exception now
            ThrowInstanceBasedFailureFromResults(andResults);

            // For remaining pending authorizations requiring database access, get the existence checks SQL fragments
            var pendingAndStrategies = andResults
                                       // Only check any strategies that have no failures
                                       .Where(x => x.FilterResults.Any(f => f.Result.State == AuthorizationState.NotPerformed))
                                       .Select(x =>
                                               new AuthorizationStrategyFilterResults
            {
                AuthorizationStrategyName = x.AuthorizationStrategyName,
                Operator      = x.Operator,
                FilterResults = x.FilterResults
                                .Where(y => y.Result.State == AuthorizationState.NotPerformed)
                                .ToArray(),
            })
                                       .ToArray();

            var orResults = PerformInstanceBasedAuthorization(authorizationFiltering, authorizationContext, FilterOperator.Or);

            bool orConditionAlreadySatisfied = orResults
                                               .Any(r => r.FilterResults.All(f => f.Result.State == AuthorizationState.Success));

            if (orConditionAlreadySatisfied || !orResults.Any())
            {
                // Check for pending ANDs
                if (pendingAndStrategies.Any())
                {
                    // Execute SQL to determine AND results
                    await PerformViewBasedAuthorizationAsync(pendingAndStrategies, authorizationContext, cancellationToken);
                }

                // We're authorized...
                return;
            }

            // We'll need to go to the database to check for relationship existence
            var pendingOrStrategies = orResults
                                      // Only check any strategies that have no failures
                                      .Where(x => x.FilterResults.All(f => f.Result.State != AuthorizationState.Failed))
                                      .Select(
                x => new AuthorizationStrategyFilterResults
            {
                AuthorizationStrategyName = x.AuthorizationStrategyName,
                Operator      = x.Operator,
                FilterResults = x.FilterResults
                                .Where(y => y.Result.State == AuthorizationState.NotPerformed)
                                .ToArray(),
            });

            var allPendingExistenceChecks =
                pendingAndStrategies.Where(x => x.FilterResults.Any())
                .Concat(pendingOrStrategies.Where(x => x.FilterResults.Any()))
                .ToArray();

            // If there are no pending view-based checks to be performed and we're still here, the authorization failure is held in the orResults
            if (!allPendingExistenceChecks.Any())
            {
                ThrowInstanceBasedFailureFromResults(orResults);
            }

            await PerformViewBasedAuthorizationAsync(allPendingExistenceChecks, authorizationContext, cancellationToken);

            bool IsCreateUpdateOrDelete(EdFiAuthorizationContext authorizationContext)
            {
                return((_bitValuesByAction.Value[authorizationContext.Action.Single().Value]
                        & (Actions.Create | Actions.Update | Actions.Delete)) != 0);
            }

            void ExecuteAuthorizationValidationRules(
                EdFiAuthorizationContext edFiAuthorizationContext,
                AuthorizationBasisMetadata authorizationBasisMetadata1)
            {
                // If there are explicit object validators, and we're modifying data
                if (_explicitObjectValidators.Any() && IsCreateUpdateOrDelete(edFiAuthorizationContext))
                {
                    // Validate the object using explicit validation
                    var validationResults = _explicitObjectValidators.ValidateObject(
                        edFiAuthorizationContext.Data,
                        authorizationBasisMetadata1.ValidationRuleSetName);

                    if (!validationResults.IsValid())
                    {
                        throw new ValidationException(
                                  string.Format(
                                      "Validation of '{0}' failed.\n{1}",
                                      edFiAuthorizationContext.Data.GetType().Name,
                                      string.Join("\n", validationResults.GetAllMessages(indentLevel: 1))));
                    }
                }
            }

            AuthorizationStrategyFilterResults[] PerformInstanceBasedAuthorization(
                IReadOnlyList <AuthorizationStrategyFiltering> authorizationStrategyFilterings,
                EdFiAuthorizationContext authorizationContext1,
                FilterOperator filterOperator)
            {
                var andResults = authorizationStrategyFilterings
                                 .Where(asf => asf.Operator == filterOperator)
                                 .Select(
                    s => new AuthorizationStrategyFilterResults
                {
                    AuthorizationStrategyName = s.AuthorizationStrategyName,
                    Operator      = s.Operator,
                    FilterResults = s.Filters
                                    .Select(
                        f => new
                    {
                        FilterDefinition = _authorizationFilterDefinitionProvider.GetFilterDefinition(f.FilterName),
                        FilterContext    = f
                    })
                                    .Select(
                        x => new FilterAuthorizationResult
                    {
                        FilterDefinition = x.FilterDefinition,
                        FilterContext    = x.FilterContext,
                        Result           = x.FilterDefinition.AuthorizeInstance(authorizationContext1, x.FilterContext)
                    })
                                    .ToArray()
                })
                                 .ToArray();

                return(andResults);
            }

            void ThrowInstanceBasedFailureFromResults(AuthorizationStrategyFilterResults[] results)
            {
                results.SelectMany(x => x.FilterResults)
                .Where(fr => fr.Result.State == AuthorizationState.Failed)
                .ForEach(fr => throw fr.Result.Exception);
            }
        }