ChilliCream / graphql-platform

Welcome to the home of the Hot Chocolate GraphQL server for .NET, the Strawberry Shake GraphQL client for .NET and Banana Cake Pop the awesome Monaco based GraphQL IDE.
https://chillicream.com
MIT License
5.1k stars 725 forks source link

Support authorization on Apollo Federation _entities query #6546

Open jeffclary opened 10 months ago

jeffclary commented 10 months ago

Product

Hot Chocolate

Is your feature request related to a problem?

I want to use a .NET AuthorizationHandler to authorize entity resolution, that is, calls to the _entities query.

I have successfully set up .NET authorization in a project so that regular methods of the top-level Query class, annotated with [Authorize("SomeRequirement")], are getting authorized as expected.

There seems to be no way in the current stable version (13.5.1 at the time of this writing) to make that authorization apply to the _entities query. Here are the things I've tried:

Using any of the methods above calling the _entities query does not trigger any authorization, as far as I can tell.

I've spent some time trying to understand how HotChocolate .NET authorization works, and it seems that for the _entities query that AuthorizationTypeInterceptor is not getting triggered.

It's entirely possible that I'm missing something obvious to make this work. If so, just close this issue with a comment pointing to some sample code and I'll be very grateful!

The solution you'd like

I want to be able to authorize Apollo Federation entity resolution (the _entities query) the same way as regular queries.

jeffclary commented 9 months ago

@michaelstaib, can you verify whether I am right above that authorization does not currently apply to the _entities query? Thanks.

darren-clark commented 9 months ago

What I see is that no field resolver level extensions function for entities, which kind of makes some sense since the resolver itself is not a field(the field is _entities), but it does make things annoying. Internally the reference resolvers are FieldResolverDelegates so it seems that this wouldn't be too much of a stretch.

jeffclary commented 9 months ago

It seems like this makes HotChocolate Apollo federation a no-go for most use cases. Authorization is not optional.

I hope the answer isn't to switch to fusion.

rohinz commented 8 months ago

Any updates for the authorization issue of reference resolvers? When can we expect a fix for it?

michaelstaib commented 8 months ago

We will have a look at this next week.. I will include it in the next patch release.

smclewin commented 8 months ago

Thank you. I am glad this can be addressed soon.

michaelstaib commented 7 months ago

https://github.com/ChilliCream/graphql-platform/pull/6769

willgittoes commented 6 months ago

I worked around this by using ApplyPolicy.Validation which does still fire for _entities

darren-clark commented 6 months ago

I worked around this by using ApplyPolicy.Validation which does still fire for _entities

I couldn't use ApplyPolicy.Validation but worked around with with

     .AddQueryType(d =>
            {
                d.Name("Query").Authorize();
                d.Extend().OnBeforeCompletion((ctx, definition) =>
                {
                    // There is probably a better way to do this.
                    // But the _service and _entities fields don't exist until after the federation type interceptor has run
                    // and it doesn't check if the fields already exist, or have any way to modify the creation
                    var serviceField = definition.Fields.Single(f => f.Name == "_service");
                    var serviceFieldDescriptor = ObjectFieldDescriptor.From(ctx.DescriptorContext, serviceField);
                    serviceFieldDescriptor.AllowAnonymous();

                    var entityField = definition.Fields.Single(f => f.Name == "_entities");
                    var entityFieldDescriptor = ObjectFieldDescriptor.From(ctx.DescriptorContext, entityField);
                    entityFieldDescriptor.Authorize();
                });
            })
willgittoes commented 6 months ago

I worked around this by using ApplyPolicy.Validation which does still fire for _entities

I couldn't use ApplyPolicy.Validation but worked around with with

This is much nicer than how I was working around it, so definitely do this instead.

jeffclary commented 6 months ago

I couldn't use ApplyPolicy.Validation but worked around with with

     .AddQueryType(d =>
            {
                d.Name("Query").Authorize();
                d.Extend().OnBeforeCompletion((ctx, definition) =>
                {
...
                    entityFieldDescriptor.Authorize();
                });
            })

I can sort of get this to work, but as quoted above I end up with a directive that has no policy. I can add a policy to the Authorize call above and see it on authorization, but in my use case I want a different policy for each different type of entity resolved. It seems like I should be able to annotate the entity type or maybe the entity resolver, but I've tried all that to no avail.

darren-clark commented 6 months ago

Yah , I don't think you can do that currently, since the return type of _,entities is any there's no "field" to attach it to.

The primary issue is that none of the usual field middleware attributes are applied to reference resolvers. This is not only Authorize but also UseProjection and some DI doesn't work the same.

I believe this is getting addressed in HC 14 by properly implementing the field middleware. Last week Michael said he had a branch he hoped to merge by last Friday.

On Thu, Jan 25, 2024, 11:47 AM Jeff Clary @.***> wrote:

I couldn't use ApplyPolicy.Validation but worked around with with

 .AddQueryType(d =>            {                d.Name("Query").Authorize();                d.Extend().OnBeforeCompletion((ctx, definition) =>                {...                    entityFieldDescriptor.Authorize();                });            })

I can sort of get this to work, but as quoted above I end up with a directive that has no policy. I can add a policy to the Authorize call above and see it on authorization, but in my use case I want a different policy for each different type of entity resolved. It seems like I should be able to annotate the entity type or maybe the entity resolver, but I've tried all that to no avail.

— Reply to this email directly, view it on GitHub https://github.com/ChilliCream/graphql-platform/issues/6546#issuecomment-1910881505, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACEVOY6NXEHYGHBX7Q2HYCDYQKZEDAVCNFSM6AAAAAA4763P3KVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMJQHA4DCNJQGU . You are receiving this because you commented.Message ID: @.***>