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; foreach (var selection in selectionSet.Selections) { var d = selection; var dd = selection.ToString(); } /* * var queryQ = from item in selectionSet.Selections * where _settings.Value.Query.OptOut.Contains(item.) * select item; */ } var opType = op.OperationType; var query = from item in op.SelectionSet.Selections select((GraphQL.Language.AST.Field)item).Name; if (op.OperationType == OperationType.Mutation && !authenticated) { 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 != null) { var rcQuery = (from requiredClaim in requiredClaims let c = requiredClaim.Type select c).ToList(); canAccess = requiredClaims.All(x => { var result = false; foreach (var ce in user.Claims) { if (ce.Type == x.Type) { if (string.IsNullOrEmpty(x.Value)) { result = true; } else { result = x.Value == ce.Value; } } } return(result); }); } // 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 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); }