Skip to content

Instantly share code, notes, and snippets.

@carlwoodhouse
Last active July 5, 2024 03:59
Show Gist options
  • Save carlwoodhouse/acc080aeba298499fa1c5d66876f6d8d to your computer and use it in GitHub Desktop.
Save carlwoodhouse/acc080aeba298499fa1c5d66876f6d8d to your computer and use it in GitHub Desktop.
using System;
using System.Threading.Tasks;
using GraphQL.Language.AST;
using GraphQL.Validation;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Localization;
using OrchardCore.Apis.GraphQL;
namespace Some.Nsamespace.ValidationRules
{
public class IntrospectionPermissionsValidationRule : IValidationRule
{
private readonly IAuthorizationService _authorizationService;
protected readonly IStringLocalizer S;
public IntrospectionPermissionsValidationRule(
IAuthorizationService authorizationService)
{
_authorizationService = authorizationService;
}
public async Task<INodeVisitor> ValidateAsync(ValidationContext validationContext)
{
var userContext = (GraphQLUserContext)validationContext.UserContext;
return await Task.FromResult(new NodeVisitors(
new MatchingNodeVisitor<Field>(async (fieldAst, validationContext) =>
{
if ((fieldAst.Name?.StartsWith("__", StringComparison.InvariantCulture) ?? false) && fieldAst.Name != "__typename" && !(await AuthorizeAsync(userContext)))
{
validationContext.ReportError(new IntrospectionNotAllowedError(validationContext, fieldAst));
}
})
));
}
private async Task<bool> AuthorizeAsync(GraphQLUserContext context)
{
return await _authorizationService.AuthorizeAsync(context.User, Permissions.CanExecuteGraphQLIntrospectionQueries);
}
}
internal class IntrospectionNotAllowedError : ValidationError
{
internal const string _code = "Unauthorized";
public IntrospectionNotAllowedError(ValidationContext context, Field node)
: base(context.Document.OriginalQuery, _code, "Introspection is not allowed.", node)
{
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment