Esempio n. 1
0
        public INodeVisitor Validate(ValidationContext context)
        {
            var userContext = context.UserContext.As <GraphQLUserContext>();
            var user        = userContext.HttpContextAccessor.HttpContext.User;

            IEnumerable <string> claimsEnumerable = (from item in user.Claims
                                                     let c = item.Type
                                                             select c).ToList();
            //            IEnumerable<string> claimsEnumerable = query.ToList();
            var authenticated = user?.Identity.IsAuthenticated ?? false;

            var myEnterLeaveListenerSink       = new MyEnterLeaveListenerSink();
            var currentEnterLeaveListenerState = (ICurrentEnterLeaveListenerState)myEnterLeaveListenerSink;
            var myEnterLeaveListener           = new MyEnterLeaveListener(_ =>
            {
                _.Match <Operation>(op =>
                {
                    if (!authenticated)
                    {
                        //                        var usages = context.GetRecursiveVariables(op).Select(usage => usage.Node.Name);
                        //                        var selectionSet = op.SelectionSet;
                        if (op.OperationType == OperationType.Mutation)
                        {
                            context.ReportError(new ValidationError(
                                                    context.OriginalQuery,
                                                    "auth-required",
                                                    $"Authorization is required to access {op.Name}.",
                                                    op));
                        }
                    }
                });

                _.Match <Field>(fieldAst =>
                {
                    var currentFieldPath     = currentEnterLeaveListenerState.EnterLeaveListenerState.CurrentFieldPath;
                    var currentOperationType = currentEnterLeaveListenerState.EnterLeaveListenerState.OperationType;
                    var requiredClaims       = _graphQLFieldAuthority
                                               .FetchRequiredClaimsAsync(currentOperationType, currentFieldPath).Result;
                    var canAccess = true;
                    if (requiredClaims.StatusCode == GraphQLFieldAuthority_CODE.FOUND)
                    {
                        if (!authenticated)
                        {
                            canAccess = false;
                        }
                    }

                    if (canAccess &&
                        requiredClaims != null &&
                        requiredClaims.Value.Any())
                    {
                        canAccess = CanAccess(requiredClaims, user);
                    }

                    //  var canAccess = rcQuery.All(x => claimsEnumerable?.Contains(x) ?? false);
                    if (!canAccess)
                    {
                        context.ReportError(new ValidationError(
                                                context.OriginalQuery,
                                                "auth-required",
                                                $"You are not authorized to run this query.",
                                                fieldAst));
                    }
                });

                /*
                 * // this could leak info about hidden fields in error messages
                 * // it would be better to implement a filter on the schema so it
                 * // acts as if they just don't exist vs. an auth denied error
                 * // - filtering the schema is not currently supported
                 * _.Match<Field>(fieldAst =>
                 * {
                 *  var fieldDef = context.TypeInfo.GetFieldDef();
                 *  if (fieldDef.RequiresPermissions() &&
                 *      (!authenticated || !fieldDef.CanAccess(userContext.User.Claims)))
                 *  {
                 *      context.ReportError(new ValidationError(
                 *          context.OriginalQuery,
                 *          "auth-required",
                 *          $"You are not authorized to run this query.",
                 *          fieldAst));
                 *  }
                 * });
                 */
            });

            myEnterLeaveListener.RegisterEventSink(myEnterLeaveListenerSink);
            return(myEnterLeaveListener);
        }
        public INodeVisitor Validate(ValidationContext context)
        {
            var myEnterLeaveListenerSink       = new MyEnterLeaveListenerSink();
            var currentEnterLeaveListenerState = (ICurrentEnterLeaveListenerState)myEnterLeaveListenerSink;
            var myEnterLeaveListener           = new MyEnterLeaveListener(_ =>
            {
                _.Match <Operation>(op =>
                {
                    var opType = op.OperationType;
                    var query  = from item in op.SelectionSet.Selections
                                 select((GraphQL.Language.AST.Field)item).Name;
                    if (op.OperationType == OperationType.Mutation)
                    {
                        context.ReportError(new ValidationError(
                                                context.OriginalQuery,
                                                "auth-required",
                                                $"Authorization is required to access {op.Name}.",
                                                op));
                    }
                });

                _.Match <Field>(fieldAst =>
                {
                    var currentFieldPath     = currentEnterLeaveListenerState.EnterLeaveListenerState.CurrentFieldPath;
                    var currentOperationType = currentEnterLeaveListenerState.EnterLeaveListenerState.OperationType;
                    var requiredClaims       = _graphQLFieldAuthority
                                               .FetchRequiredClaimsAsync(currentOperationType, currentFieldPath).Result;
                    var canAccess = true;



                    //  var canAccess = rcQuery.All(x => claimsEnumerable?.Contains(x) ?? false);
                    if (!canAccess)
                    {
                        context.ReportError(new ValidationError(
                                                context.OriginalQuery,
                                                "auth-required",
                                                $"You are not authorized to run this query.",
                                                fieldAst));
                    }
                });

                /*
                 * // this could leak info about hidden fields in error messages
                 * // it would be better to implement a filter on the schema so it
                 * // acts as if they just don't exist vs. an auth denied error
                 * // - filtering the schema is not currently supported
                 * _.Match<Field>(fieldAst =>
                 * {
                 *  var fieldDef = context.TypeInfo.GetFieldDef();
                 *  if (fieldDef.RequiresPermissions() &&
                 *      (!authenticated || !fieldDef.CanAccess(userContext.User.Claims)))
                 *  {
                 *      context.ReportError(new ValidationError(
                 *          context.OriginalQuery,
                 *          "auth-required",
                 *          $"You are not authorized to run this query.",
                 *          fieldAst));
                 *  }
                 * });
                 */
            });

            myEnterLeaveListener.RegisterEventSink(myEnterLeaveListenerSink);
            return(myEnterLeaveListener);
        }