Hi,
my current project is using vertx-web-graphql module.
I have a real problem with authentication and authorization during subscription process. I know that the problem with authentication and authorization with WebSocket is well known.
Anyway, I've found that during the first call, Reactjs Apollo client sends a message with authToken. This message could be captured inside message handler in the following way:
val apolloWSHandler = ApolloWSHandler
.create(graphQL)
.messageHandler {
if (it.type() == ApolloWSMessageType.CONNECTION_INIT) {
println(it.content())
}
}
This way I can filter for token and validate user and that could be one way of blocking unwanted request.
Unfortunatelly, that doesn't solve the authorization problem inside data fetchers. DataFetcher doesn't have anyting in common with ApolloWSHandler.
I didn't find a way to pass some values from ApolloWSHandler handlers to Graphql context. For some reason I thought that will be done out of box :-(
Specialized type of DataFetcher is VertxDataFetcher that receives DataFetchingEnrironment and Promise as method arguments during execution.
I found very easy implementation for Query and Mutation over Graphql and HTTP. That wasn't the case with Apollo WebSocket implementation.
The main difference between HTTP and WS is that method getContext() on environment object returns:
RoutingContext when use HTTP ( as expected )
Unit ( Void ) when use WS for subscription
I know that WebSocket doesn't have RoutingContext during execution, all messages are part of one connection in multiplex world, but I hoped that it would be possible to have some kind of session management available inside environment.
DataFetcher for Query over HTTP:
VertxDataFetcher<String> { env, prom ->
val context = env.getContext<RoutingContext>()
context.request().headers().forEach(::println)
prom.complete("Hello From Graphql")
}
DataFetcher for Subscription over WebSocket:
VertxDataFetcher<String> { env, prom ->
// env.getContext() returns Unit
// in this moment I need some user reference
prom.complete("Hello From Graphql")
}
I didn't find any documentation about this kind of usage. Maybe I'm missing something on the concept level.
Only one solution that could give me required information for subscription authorization is passing another token inside payload but honestly I think that some kind of session management should be much more efficient and secure.
Any suggestion is welcome