Hotchocolate: Trying to get Authorize directive to work with my DefaultAuthorizationPolicyProvider

Created on 26 Nov 2019  ·  12Comments  ·  Source: ChilliCream/hotchocolate

I'm trying to get my .Net Core 3.0 API project to use my IAuthorizationPolicyProvider and IAuthorizationHandler that are registered. I've created a policy provider and authorization handler that work with the Authorize(PolicyName) attribute for regular API controllers. I'm using JWT based authentication and that's set up in the ConfigureServices method in Startup.cs before GraphQL. In the Configure method in Startup.cs, CORS, Authentication, and Authorization are all setup before GraphQL as well.

A cleaned up version of my query type with the Authorize call is below.

public class MyQueryType : ObjectType<MyQuery>
    {
        protected override void Configure(IObjectTypeDescriptor<MyQuery> myQueryDescriptor)
        {
            myQueryDescriptor.Field(t => t.GetStuffFromRepository())
                .Name("StuffFromRepository")
                .UseFiltering()
                .UseSorting()
                .Authorize("ReadStuffFromRepositoryPolicy");
                .....

When I'm running in debug, I can get to my Handler and Policy Providers when I hit the API controller, but when I hit the GraphQL endpoint I get a "The current user is not authorized to access this resource." message and it doesn't seem to hit my Handler nor the Policy Provider.

Any suggestions? BTW great project and we're really loving how easy it's been to wire up and expose basic EF models as GraphQL objects - thanks for all the great work!

❓ question 🔍 investigate

All 12 comments

Can you provide a little repro? It is always easier to point to the issue with some code.

Ok slimmed down my project and created a new repo: https://github.com/mikelee516/HotChocolate.Spike

It's the same deal where you can hit the "Pass" attributed API endpoint and get denied for the "Deny" attributed API endpoint. I then use the same policy names for the GraphQL endpoints and get user not authorized on both. Let me know if I need to clarify anything.

Where are your policies defined? Can you post a link to that?

My policy set up is super simplified, basically if something is attributed with Authorize and the policy name is "Pass" then you get access, any other name will be denied. Ultimately the authorization or denial is done in the Handler (https://github.com/mikelee516/HotChocolate.Spike/blob/master/Authorization/MyAuthorizationHandler.cs) and the policy is set up in the Provider (https://github.com/mikelee516/HotChocolate.Spike/blob/master/Authorization/MyPolicyProvider.cs)

Ok finally carved out some time to really look at this and debug, so it comes down to AuthorizeMiddleware in the HotChocolate.AspNetCore.Authorization project. Somehow the ClaimsPrincipal is coming in as not authenticated and so since the caller is not authenticated and thus not allowed, none of the other logic is fired to check against the policy. I don't see any of my authorization code being called so there's something that needs to set the principal as authenticated.

I can see the call stack from the QueryMiddleBase, I'm assuming that is due to HotChocolate being setup to accept requests on the path. Any ideas on what I can do here?

In my case for the actual project i'm working on, this looks like it might be how we implemented the JWT Authentication. I'll take a deeper look into that and report back if that's the case.

We have an interceptor so you can change how we acquire the claims principal.

I am closing this since all questions were answered.

Had the same problem and it occurs if AddAuthorization is not called in Startup.cs ConfigureServices.
Because its a very subtle bug, I had to add HotChocolate.Authorization source for pinpointing the issue.
@michaelstaib It would be very helpful if a error is thrown in AuthorizeMiddleware on line 117 if policy is not empty.

After doing what @nkovacic suggested, and switching to Windows Authentication, I was able to get the policies to work with the Authorize middleware. Most likely I royally screwed up the JWT set up but I'm not sure and I hope to figure it out at some point. I'll post an update the GitHub example I had when I get that working as well (I got the one at work working and I'll take it from there)

@nkovacic this is not an error since you could use role based security and you may or may not have them combined with policies.

Or maybe you just want an auth check....

However, we have started to refactor the middleware.... we will need a few more iterations to get the nicer-

JWT auth is different in the sense that it requires anonymous access to token e.g. Beaer auth header of http request. When configure the authorization service in configureservices of startup.cs, need to create a policy and ensure that policy requirement is not the default Deny anonymous. It can be easily achieved with requireassert returning true () => true. @mikelee516

Was this page helpful?
0 / 5 - 0 ratings