Search code examples
asp.net-coregraphqlasp.net-authorizationhotchocolate

HandleRequirementAsync not being called when using authorization in Hot Chocolate


Hi,

I am trying to implement policy-based authorization in a Hot Chocolate graphql server. I am looking at their documentation and also referring to Microsoft's guide

What I want to achieve

I want that HandleRequirementAsync() will be called whenever a User query is being called.

What I've done
  1. I register authorization and the User Policy in ConfigureServices
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddHttpContextAccessor();
            services.AddAuthorization(options =>
            {
                options.AddPolicy("UserPolicy",
                policy => policy.Requirements.Add(new UserRequirement()));
            });


            services.AddSingleton<Query>();

            services.AddSingleton<IAuthorizationHandler, UserAuthorizationHandler>();

            services.AddSingleton(typeof(IUserRepo), typeof(UserRepo));
            services.AddSingleton(typeof(IBookRepository), typeof(BookRepository));

            services.AddGraphQL(
                SchemaBuilder.New()
                    .AddAuthorizeDirectiveType()
                    .AddType<UserType>()
                    .AddType<BookType>()
                    .AddQueryType<Query>());
        }
  1. I have the User requirement class and the handler
 public class UserAuthorizationHandler : AuthorizationHandler<UserRequirement, IResolverContext>
    {
        private IHttpContextAccessor _accessor;

        public UserAuthorizationHandler([Service] IHttpContextAccessor accessor)
        {
            _accessor = accessor;
        }

        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, UserRequirement requirement,
            IResolverContext resource)
        {
            context.Succeed(requirement);
            return Task.CompletedTask;
        }
    }

    public class UserRequirement : IAuthorizationRequirement
    {
    }
  1. I declared one field to require the policy authorization.
    public class UserType
        : ObjectType<User>
    {
        protected override void Configure(IObjectTypeDescriptor<User> descriptor)
        {
            descriptor.Field(t => t.Name).Type<NonNullType<StringType>>().Authorize("UserPolicy");
            descriptor.Field(t => t.Id).Type<NonNullType<StringType>>();
        }
    }

The problem

When running this code. I expect that the HandleRequirementAsync will be called. This method should always succeed. However, when requesting for user. What actually happens is the the method is not called and the request is immediately denied with this following response:

{
  "errors": [
    {
      "message": "The current user is not authorized to access this resource.",
      "locations": [
        {
          "line": 3,
          "column": 5
        }
      ],
      "path": [
        "user",
        "name"
      ],
      "extensions": {
        "code": "AUTH_NOT_AUTHENTICATED"
      }
    }
  ]
}

Solution

  • I just had an alike problem. In my case I had to ensure that in

            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    

    I had

    app.UseAuthentication();
    app.UseAuthorization();
    

    first and then

    app.UseWebSockets()
                    .UseGraphQL("/graphql")
                    .UsePlayground("/graphql")
                    .UseVoyager("/graphql");