19

I have a Spring MVC server that provides a bunch of REST endpoints as well as a websocket endpoint. Everything except the login endpoint requires authentication. I'm using JWT to authenticate requests coming from the client.

When the user logs in I'm returning an X-AUTH-TOKEN header, containing the JWT token. This token is then passed in the same header on every request to the server. This all works fine for the REST endpoints, but I can't figure out how to do this on the websocket.

I'm using SockJS, and when I open the connection:

var socket = new SockJS('/socket/updates', null, {});

This causes a GET request to /socket/updates/info?t=xxx which returns a 403 (as everything requires auth by default).

Ideally I'd simply send my X-AUTH-TOKEN header on any XHR requests SockJS makes, but I can't see any way of adding headers looking at the API.

Worst case I can change SockJS to do this, but I'm wondering whether this functionality has been deliberately left out? I know SockJS doesn't support cookies for security reasons but that's not what I'm trying to do.

Also, for the sake of a test I did allow the info endpoint to have anonymous access but then it 403's on a bunch of other endpoints - it feels more elegant to simply pass in auth details on these requests than poke holes in my server security.

Any help appreciated.

Cheers

L Morris
  • 251
  • 1
  • 2
  • 5

2 Answers2

6

You cannot set the header from SockJS. Not because SockJS does not have this functionality, but because browser makers don't expose this API to Javascript. See:

https://github.com/sockjs/sockjs-client/issues/196

For a workaround, see JSON Web Token (JWT) with Spring based SockJS / STOMP Web Socket.

Community
  • 1
  • 1
Raman
  • 17,606
  • 5
  • 95
  • 112
  • 7
    any change so far? Does it work now in 2019? I've tried new ```SockJS(url, {headers : {Authorization : 'Bearer ' }}``` and when I debug in the dev console tab network, I see that the request doesn't have a Authorization header (headers are not taken into account) – hzitoun Jul 19 '19 at 14:23
  • 3
    May be now any changes in 2022?)) – Митяй Apr 03 '22 at 06:33
0

client side:

stompClient.connect({headername:header}, function () {
                setConnected(true);
                stompClient.subscribe(request.topic, function (message) {
                    output(message.body);
                });
            });

server side :

StompHeaderAccessor accessor
                        = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);

 String headervalue= accessor.getNativeHeader("your header name").get(0);
ahll
  • 2,329
  • 1
  • 19
  • 22
  • 7
    This sets STOMP header, not an HTTP header, so as it may be a part of workaround it does not solve initial issue which is unability to add custom HTTP header to the SockJS handshake request. – Plebejusz Feb 06 '18 at 13:47
  • Well, it looks like this approach is the recommended one by Spring in the case when no HttpSession is maintained(i.e. when `http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)` ). https://github.com/spring-projects/spring-framework/blob/master/src/docs/asciidoc/web/websocket.adoc#token-authentication – egelev Dec 12 '19 at 21:55