How to authenticate user using subscription #134
-
Currently I can validate my user authentication using spring security by passing the access_token in the subscription endpoint:
In the above example I am able to successful connect to the websocket, However when I try to get the authentication object when I receive a message in the connection using It's possible to manual authentication the user by querying the connection request? If yes, can you please help me with this one? |
Beta Was this translation helpful? Give feedback.
Replies: 14 comments 5 replies
-
@guitcastro were you able to get it to work successfully. we are looking to use Spring security to authenticate the token and then access the token in the subscription message handling. |
Beta Was this translation helpful? Give feedback.
-
@kapilnayar Any news on this regards please comment in here. |
Beta Was this translation helpful? Give feedback.
-
@guitcastro I've created a sample app here: https://github.com/graphql-java-kickstart/samples/tree/master/subscription-with-authentication. Besides the obvious Java backend you'll find a small react frontend in the There's no readme yet, so just code for now. It's also clear from this sample project that In const wsLink = new WebSocketLink({
uri: `ws://localhost:9000/subscriptions`,
options: {
reconnect: true,
connectionParams: {
authToken: 'foobar',
}
}
}); The key part in the backend is to add your own public Optional<Object> onConnect(Object payload) {
log.debug("onConnect with payload {}", payload.getClass());
String token = ((Map<String, String>) payload).get("authToken");
log.info("Token: {}", token);
return Optional.of(token);
} Then in Publisher<Integer> hello(DataFetchingEnvironment env) {
GraphQLContext context = env.getContext();
Optional<String> token = context.getSession()
.map(Session::getUserProperties)
.map(props -> props.get(ApolloSubscriptionConnectionListener.CONNECT_RESULT_KEY))
.map(String.class::cast);
log.info("Subscribe to publisher with token: {}", token);
return publisher;
} In this case I simply returned this It's a work in progress and as stated would be nice to create an easier to use feature in |
Beta Was this translation helpful? Give feedback.
-
@oliemansm Thanks for the response. I can get the user authentication using the
However this is not integrated with spring security, where I can get the user using: |
Beta Was this translation helpful? Give feedback.
-
@guitcastro This project doesn't provide any integration out of the box for securing regular queries using Spring Security either. In that case you'd have to write your own filter and add it to the security chain to populate the I only took a look now how to integrate authentication using subscriptions in the first place. This could serve as a basis to investigate next steps how to integrate this with Spring Security. |
Beta Was this translation helpful? Give feedback.
-
@guitcastro public Optional<Object> onConnect(Object payload) {
log.debug("onConnect with payload {}", payload.getClass());
String token = ((Map<String, String>) payload).get("authToken");
log.info("Token: {}", token);
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(token, null));
return Optional.of(token);
} Then in my publisher I could get a hold of it using Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); If you start a separate thread at that time and you want to be able to use method based security you'd have to pass the |
Beta Was this translation helpful? Give feedback.
-
@oliemansm Amazing! That's exactly what I was looking for! |
Beta Was this translation helpful? Give feedback.
-
Perhaps we could create a small |
Beta Was this translation helpful? Give feedback.
-
@oliemansm That makes sense; I will reopen the issue. Although a documentation update may be enough |
Beta Was this translation helpful? Give feedback.
-
Sample showing usage is now available here: https://github.com/graphql-java-kickstart/samples/tree/master/subscription-with-authentication. Still needs a README though to explain it a bit. |
Beta Was this translation helpful? Give feedback.
-
Hi, I tried using this sample and I noticed the following: I get the following ClassCastException:
I'm trying to protect the graphql endpoint with oauth2 and jwt. So I'm a bit confused now on how to properly secure a graphql endpoint including the subscriptions, because when I don't cast it, my request seems to hang when POST a subscription, unable to receive data. |
Beta Was this translation helpful? Give feedback.
-
I am using method based security and sometimes the SecurityContextHolder.getContext().getAuthentication() seems to be an
You said, that we need to pass the Seems to work when using: |
Beta Was this translation helpful? Give feedback.
-
This seems to work sometimes but not always! working case:
not working:
This seems to be randomly working and not working. Any thoughts or ideas why this is functioning like this and how I can solve this? |
Beta Was this translation helpful? Give feedback.
-
See Spring Security authorization example of GraphQL subscriptions for graphql-java-kickstart server here |
Beta Was this translation helpful? Give feedback.
@guitcastro
I was able to get a hold of the principal in my publisher by setting the authentication in the
SecurityContext
in theConnectionListener
Then in my publisher I could get a hold of it using
If you start a separate thread at that…