I have a functional project of chat by websockets that is already working, now I need to implement authentication by JWT. This is the flow of the requests
ws://localhost:port/chatting
/user/{userId}/queue/chatting
{ 'message': msg, 'from': "userId", 'to': "recipientId" }
, and the system will redirect them to /user/{recipientId}/queue/chatting
I would like to secure:
from
inside bodyFirst of all adding authentication can be done by configuring the same in WebSecurityConfig
, adding a custom JwtRequestFilter
which is going to parse you JWT token and set the authentication context for that request.
A good reference for the same: create-apis-with-jwt-authorization-using-spring-boot.
Regarding 2 and 3, Springboot does not allow exposing dynamic endpoints for STOMP registration, so you will have to expose /user/queue/chatting
and clients will have to directly subscribe to this. However, using convertAndSendToUser(userId, destination, payload) you can send the message based on the userId. This function internally calls this function which does this this.destinationPrefix(/user) + user(/username) + destination(/queue/chatting)
so as you can see the variable user
is getting prefixed to final destination, you can pass userId instead of userName.
Reference for this: simpMessagingTemplate.convertAndSendToUser
But do note in this case you would have to set the username for this session as userId itself. This can be done in your custom JwtRequestFilter
private void populateSecurityContextHolder(HttpServletRequest request, String userId, List<SimpleGrantedAuthority> grantedAuthorities) {
PreAuthenticatedAuthenticationToken authToken = new PreAuthenticatedAuthenticationToken(
userId, null, grantedAuthorities);
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
log.info("Authentication set for userId " + userId);
}
So with this, your server can send messages based on userId it receives in the messages.