/// <summary>
        /// Called by the runtime to invoke the middleware logic. In most cases, the middleware component should return the task
        /// generated by calling the next delegate in the request chain with the provided context.
        /// </summary>
        /// <param name="context">The invocation request governing data in this pipeline run.</param>
        /// <param name="next">The next delegate in the chain to be invoked.</param>
        /// <param name="cancelToken">The cancel token.</param>
        /// <returns>Task.</returns>
        public async Task InvokeAsync(GraphFieldExecutionContext context, GraphMiddlewareInvocationDelegate <GraphFieldExecutionContext> next, CancellationToken cancelToken)
        {
            FieldAuthorizationResult result = FieldAuthorizationResult.Default();

            if (context.IsValid)
            {
                // execute the authorization pipeline
                var authRequest = new GraphFieldAuthorizationRequest(context.Request);
                var authContext = new GraphFieldAuthorizationContext(context, authRequest);
                await _authPipeline.InvokeAsync(authContext, cancelToken).ConfigureAwait(false);

                result = authContext.Result ?? FieldAuthorizationResult.Default();

                // by default, deny any stati not explicitly declared as "successful" by this component.
                if (!result.Status.IsAuthorized())
                {
                    context.Messages.Critical(
                        $"Access Denied to field {context.Field.Route.Path}",
                        Constants.ErrorCodes.ACCESS_DENIED,
                        context.Request.Origin);
                }
            }

            if (!result.Status.IsAuthorized())
            {
                context.ResolvedSourceItems.AddRange(context.Request.DataSource.Items);
                context.ResolvedSourceItems.ForEach(x => x.Fail());
            }

            await next(context, cancelToken).ConfigureAwait(false);
        }
        /// <summary>
        /// Creates an authorization context to validate the field request this builder is creating.
        /// </summary>
        /// <returns>GraphFieldAuthorizationContext.</returns>
        public GraphFieldAuthorizationContext CreateAuthorizationContext()
        {
            var parent = this.CreateFakeParentMiddlewareContext();

            var request = new GraphFieldAuthorizationRequest(this.FieldRequest);

            return(new GraphFieldAuthorizationContext(
                       parent,
                       request));
        }
Example #3
0
        /// <summary>
        /// Iterates over every secure field in the operation on the context, attempting to authorize the
        /// user to each one.
        /// </summary>
        /// <param name="context">The primary query context.</param>
        /// <param name="cancelToken">The cancel token.</param>
        /// <returns><c>true</c> if authorization was successful, otherwise false.</returns>
        private async Task <bool> AuthorizeOperation(GraphQueryExecutionContext context, CancellationToken cancelToken)
        {
            var  authTasks      = new List <Task>();
            bool anyFieldFailed = false;

            foreach (var fieldContext in context.QueryOperation.SecureFieldContexts)
            {
                var authRequest = new GraphFieldAuthorizationRequest(fieldContext);
                var authContext = new GraphFieldAuthorizationContext(context, authRequest);

                var pipelineTask = _authPipeline.InvokeAsync(authContext, cancelToken)
                                   .ContinueWith(
                    (_) =>
                {
                    var authResult = authContext.Result ?? FieldAuthorizationResult.Default();

                    // fake the path elements from the field route. since we don't have a full resolution chain
                    // when doing query level authorization (no indexers on potential child fields since
                    // nothing is actually resolved yet)
                    if (!authResult.Status.IsAuthorized())
                    {
                        context.Messages.Critical(
                            $"Access Denied to field {fieldContext.Field.Route.Path}",
                            Constants.ErrorCodes.ACCESS_DENIED,
                            fieldContext.Origin);
                        anyFieldFailed = true;
                    }
                }, cancelToken);

                authTasks.Add(pipelineTask);
            }

            await Task.WhenAll(authTasks).ConfigureAwait(false);

            return(anyFieldFailed);
        }