Passing JWT token to SockJS

Websocket's doesn't follows the same pattern in headers with HTTP. That's why, Even if you send token in header, It could not found. I had the same issue before and I changed websocket security structure.

My sample code is this:

@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
    registration.setInterceptors(new ChannelInterceptorAdapter() {

        @Override
        public Message<?> preSend(Message<?> message, MessageChannel channel) {
            StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
            MessageHeaders headers = message.getHeaders();
            SimpMessageType type = (SimpMessageType) headers.get("simpMessageType");
            List<String> tokenList = accessor.getNativeHeader("Authorization");
            String token = null;
            if(tokenList == null || tokenList.size() < 1) {
                return message;
            } else {
                token = tokenList.get(0);
                if(token == null) {
                    return message;
                }
            }

            // validate and convert to a Principal based on your own requirements e.g.
            // authenticationManager.authenticate(JwtAuthentication(token))
            try{
                JwtAuthenticationToken jwtAuthenticationToken = new JwtAuthenticationToken(new RawAccessJwtToken(tokenExtractor.extract(token)));
                Authentication yourAuth = jwtAuthenticationProvider.authenticate(jwtAuthenticationToken);
                accessor.setUser(yourAuth);
            } catch (Exception e) {
                throw new IllegalArgumentException(e.getMessage());
            }




            // not documented anywhere but necessary otherwise NPE in StompSubProtocolHandler!
            accessor.setLeaveMutable(true);
            return MessageBuilder.createMessage(message.getPayload(), accessor.getMessageHeaders());
        }
    });

}

server-side configuration to register a custom authentication interceptor. Note that an interceptor needs only to authenticate and set the user header on the CONNECT Message. Spring notes and saves the authenticated user and associate it with subsequent STOMP messages on the same session. The following example shows how register a custom authentication interceptor:

  @Configuration
    @EnableWebSocketMessageBroker
    public class MyConfig implements WebSocketMessageBrokerConfigurer {

        @Override
        public void configureClientInboundChannel(ChannelRegistration registration) {
            registration.interceptors(new ChannelInterceptor() {
                @Override
                public Message<?> preSend(Message<?> message, MessageChannel channel) {
                    StompHeaderAccessor accessor =
                            MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
                    if (StompCommand.CONNECT.equals(accessor.getCommand())) {
                        Authentication user = ... ; // access authentication header(s)
                        accessor.setUser(user);
                    }
                    return message;
                }
            });
        }
    }

Also, note that, when you use Spring Security’s authorization for messages, at present, you need to ensure that the authentication ChannelInterceptor config is ordered ahead of Spring Security’s. This is best done by declaring the custom interceptor in its own implementation of WebSocketMessageBrokerConfigurer that is marked with @Order(Ordered.HIGHEST_PRECEDENCE + 99).

Another way : Likewise, the SockJS JavaScript client does not provide a way to send HTTP headers with SockJS transport requests. As you can see sockjs-client issue 196. Instead, it does allow sending query parameters that you can use to send a token and then with Spring you can setup some filter which will identify a session using provided token. , but that has its own drawbacks (for example, the token may be inadvertently logged with the URL in server logs).

Ref