Beispiel #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="FieldAuthorizationStartedLogEntry" /> class.
 /// </summary>
 /// <param name="context">The auth context that is being resolved.</param>
 public FieldAuthorizationStartedLogEntry(GraphFieldAuthorizationContext context)
     : base(LogEventIds.FieldAuthorizationStarted)
 {
     this.PipelineRequestId = context.Request.Id;
     this.FieldPath         = context.Field.Route.Path;
     this.Username          = context.User?.RetrieveUsername();
 }
        /// <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);
        }
Beispiel #3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="FieldAuthorizationCompletedLogEntry" /> class.
 /// </summary>
 /// <param name="context">The context.</param>
 public FieldAuthorizationCompletedLogEntry(GraphFieldAuthorizationContext context)
     : base(LogEventIds.FieldAuthorizationCompleted)
 {
     this.PipelineRequestId   = context.Request.Id;
     this.FieldPath           = context.Request.Field.Route.Path;
     this.Username            = context.User?.RetrieveUsername();
     this.AuthorizationStatus = context.Result.Status.ToString();
     this.LogMessage          = context.Result.LogMessage;
 }
Beispiel #4
0
        /// <inheritdoc />
        public virtual void FieldResolutionSecurityChallenge(GraphFieldAuthorizationContext context)
        {
            if (!this.IsEnabled(LogLevel.Trace))
            {
                return;
            }

            var entry = new FieldAuthorizationStartedLogEntry(context);

            this.LogEvent(LogLevel.Trace, entry);
        }
Beispiel #5
0
        /// <summary>
        /// Invokes this middleware component allowing it to perform its work against the supplied context.
        /// </summary>
        /// <param name="context">The context containing the request passed through the pipeline.</param>
        /// <param name="next">The delegate pointing to the next piece of middleware to be invoked.</param>
        /// <param name="cancelToken">The cancel token.</param>
        /// <returns>Task.</returns>
        public async Task InvokeAsync(GraphFieldAuthorizationContext context, GraphMiddlewareInvocationDelegate <GraphFieldAuthorizationContext> next, CancellationToken cancelToken)
        {
            context.Logger?.FieldResolutionSecurityChallenge(context);

            var result = await this.AuthorizeRequest(context.Request, context.User).ConfigureAwait(false);

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

            context.Logger?.FieldResolutionSecurityChallengeResult(context);

            await next(context, cancelToken).ConfigureAwait(false);
        }
Beispiel #6
0
        /// <inheritdoc />
        public virtual void FieldResolutionSecurityChallengeResult(GraphFieldAuthorizationContext context)
        {
            var logLevel = context.Result.Status == FieldAuthorizationStatus.Unauthorized
                ? LogLevel.Warning
                : LogLevel.Trace;

            if (!this.IsEnabled(logLevel))
            {
                return;
            }

            var entry = new FieldAuthorizationCompletedLogEntry(context);

            this.LogEvent(logLevel, entry);
        }
Beispiel #7
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);
        }
Beispiel #8
0
 /// <summary>
 /// Executes the field authorization pipeline against the provided context.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <returns>Task.</returns>
 public async Task ExecuteFieldAuthorization(GraphFieldAuthorizationContext context)
 {
     var pipeline = this.ServiceProvider.GetService <ISchemaPipeline <TSchema, GraphFieldAuthorizationContext> >();
     await pipeline.InvokeAsync(context, default).ConfigureAwait(false);
 }