micronaut-projects / micronaut-graphql

A repository for Micronaut and GraphQL integrations
Apache License 2.0
83 stars 44 forks source link

GraphQL access to underlying HttpRequest #18

Closed sillyoldman closed 5 years ago

sillyoldman commented 5 years ago

Our setup within company involves using SSL certificates for connecting to any intranet / internet website. The certificate has user information, and it is what we use to Authenticate.

In my DataFetchers I will like to know the identity of the requesting user. I had hard time trying to figure it out. I eventually did - but kinda think there must be a better way to do it.

What I did -

  1. Added HttpServerFilter, and used HttpRequest and NettyHttpRequest to get underlying SSL context to retrieve certificate.
  2. Parsed cert to get user information.
  3. Called custom Authentication / Authorization service to retrieve valid user roles. (this has to be custom as it goes to central db and is a separate microservice)
  4. Populated UserDetails and added it back to HttpRequest as an attribute.

i resorted to adding Filter because, I was not able to get my implementation of AuthenticationProvider (as mentioned in the guide but for BasicAuth) called. Most likely my lack of knowledge - but will like to know if there is a better way to implement SSLAuthenticationProvider.

By default, I don't have access to HttpRequest in DataFetchers. After going through code and debugging finally resorted to overriding / @Replaces annotation and replaced one of the framework bean (which I don't like) I Replaced DefaultGraphQLInvocation and made a small change in it to set httpRequest in the context :

ExecutionInput.newExecutionInput() .query(..).operationName(..).variables.(..) .context(httpRequest).build();

And then in my Datafetcher, I could get it from DataFetchingEnvironment. I just think, there must be a simple and better solution to this which I haven't been able to figure out.

Appreciate your help. Thanks

marceloverdijk commented 5 years ago

H @nkatakkar,

micronaut-graphql provides a GraphQLExecutionInputCustomizer to customize the ExecutionInput.

By default a DefaultGraphQLExecutionInputCustomizer singleton is created which does nothing. You could create a custom GraphQLExecutionInputCustomizer and @Replace the default.

In the custom GraphQLExecutionInputCustomizer you can indeed set a context object which can be retrieved from the data fetchers. Personally I would not directly set the HttpRequest as the context object but, a custom context container containing the HttpRequest. This way you could easily add other data to the context object in the future, without having to change your code.

Does this help?

marceloverdijk commented 5 years ago

Having said that, the question regarding the filter and the auth stuff is more a generic Micronaut (Security) question. https://gitter.im/micronautfw/questions is a good place to ask such a question as well.

sillyoldman commented 5 years ago

Thank you @marceloverdijk Yes , indeed. I will try it. I also like your suggestion of wrapping HttpRequest in a Custom My Application specific context.

A follow-up question I have is - is there a specific reason why HttpRequest is not made available via context like this ? Are there downsides ? Logically I understand that all call should come in as ?grpahql= and any additional data has no meaning from GraphQL point of view.

Also, is it possible to get User Session in DataFetchers ? GraphQL specification makes no reference to it or has no concept of it , if I understand it right. But in usual web application, Http Request and Session usage is quite common.

marceloverdijk commented 5 years ago

DataFetcher is an graphql-java interface which does know anything of the transport layer. Http in this case, and specifically a Micronaut HttpRequest). graphql-java is agnostic of the application framework you use.

Alternative for setting the HttpRequest in the execution input context is to retrieve the current request in the data fetchers via ServerRequestContext#currentRequest().

marceloverdijk commented 5 years ago

@nkatakkar Can I close this issue?

sillyoldman commented 5 years ago

Yes please. We can close this. Thank you for your help.