Currently, the WebSocket / stomp security reference documentation contains two unhelpful lines about authenticating a user on a WebSocket. They basically seems to suggest spring-websocket can only be used in a website where a user is already authenticated.

AFAIK, this is not correct given the advances in spring-session and spring-security.

I've found that finding out how to authenticate a user over spring-websocket takes you through a web of examples and gists representing various versions of spring-security, spring-session and spring-websocket, stackoverflow questions and Github issues.

It's an absolute maze. And it's something you want to do right, since if you screw up, you're opening yourself up to all sorts of disasters.

I would recommend writing documentation that explains how to authenticate, authorize, reconnect and maintain secure (csrf etc) a websocket based connection assuming a server that serves both mobile devices and browsers, discussing both server and client.

The assumption that websocket is the primary channel for mobile app communication needs to be at the basis of our understanding of how this will be used most. It's not just about a website with a chat pane.

I realize that the client side is basically outside of the scope of the core documentation. So, this could be placed in guides perhaps.

What I find missing currently: - How the session token works conceptually. - Not clear how to pass a session id token to authenticate a user on a websocket. i.e. how to (re-)activate a websocket session on a client - How to reconnect a websocket after a connection was lost (server down, no 3g etc) - How to configure front end webservers like nginx to properly process requests. The assumption is direct connection to Tomcat, which is never a production reality - How to implement csrf - What to expect in the connection flow in terms of headers and appropriate values, 101 upgrades etc. This is not clear and would help with helping newbies (like me) figure it out - [...]

It's not entire clear if this is the right place for this issue since this concern overlaps spring-session, spring-security and spring-websocket.

Comment From: ssijak

I am wanting to implement websockets in my app and found out everything that you have written about is true. No good examples on how to implement websocket auth when I am using restful api and JWT tokens to secure my api. Spring docs only have examples if you use sessions.

Comment From: mschipperheyn

I'm not even clear on what header to supply to a stomp websocket message to get a Principal. I've seen various headers described in various examples and various values of them: - HTTP.SESSION.ID - SPRING.SESSION.ID - x-auth-token - simpUser - simpSessionAttributes

There doesn't seem to be a clear description on which one to use and how. A LOT of assumptions are made about the knowledge of the developer implementing this stuff. There's also the unfortunate and incorrect assumption that all users use websocket as a secondary channel for a website, providing access to cookies etc. i think this assumption is the primary reason a lot of this documentation is screwed up.

The only thing that's clear to me is what a session id is. I'm supplying SPRING.SESSION.ID right now as a header on a message, but not getting an authenticated user at the end of that process. Wasting so much time grappling in the dark. Incredibly disappointing.

Comment From: asaarnak

You could take a look at this: Github project which is based on a "hack" in this blog post They have created a class AbstractSecurityWebSocketMessageBrokerConfig which allows setting custom securityContextChannelInterceptor

Also check out this issue: https://github.com/spring-projects/spring-security/issues/3217

Comment From: courteous

asaarnak thank you for that link. this makes much clear but what about a binary web sockets i.e.

what about situations where no stomp of rabbt mq or any text based protocols are used , instead only pure binary messages over websockets. What class "Configurer" do we need to exted from in this case?. It seems that AbstractWebSocketMessageBrokerConfigurer was beeing particularlly created with the STOMP in mind since it implements "WebSocketMessageBrokerConfigurer" which enforces me to register a basic "StompEndpoint" but what if i am not using STOMP? i am missing the class that will handle pure binary messages. i.e. something like AbstractWebSocketMessageBrokerConfigurer but for binary protocols only.

Comment From: asaarnak

Found an example how to use spring-websockets without STOMP. Spring security does'nt support websockets without STOMP. For spring-security you should extend the WebSocketConfigurer, but propably easier to just use STOMP without sockJs fallback.

Comment From: courteous

asaarnak many thanks, i guess i needed to clarify .I already did that, i.e. my app already extend WebSocketConfigurer and i am able to pass binary messages back and forth what does not work is the authentication i.e. when i after successfully creating my token and set it into the SecurityContextHolder succesefully ,

        token.setAuthenticated(true);
        SecurityContext securityContext = SecurityContextHolder.getContext();
        securityContext.setAuthentication(token);
        SecurityContextHolder.setContext(securityContext);

        sessionStrategy.onAuthentication(
                authentication,
                httpServletRequest, 
                httpServletResponce
                );

after the next binary payload is received within the same websocket when i try to access the the security context holder it is always null.

    SecurityContext  securityContext = SecurityContextHolder.getContext();
    testUser = (Users) securityContext.getAuthentication().getPrincipal();

If i do the same step but use HTTP as transport instead then it all works. Taking into account that i use the same AuthenticationProvider in bought cases i.e. only different transport. For me that means that the Security Context Holder is somehow living in the HTTP session and when that is cleared my security context is also cleared so i was hoping to find an example showing how to prevent that.

Comment From: asaarnak

You could try adding custom HandshakeInterceptor, try create something like SecurityContextChannelInterceptor, that is used by the AbstractSecurityWebSocketMessageBrokerConfig.

And then add after addHandler with:

.addHandler(yourWebSocketHandler)
.addInterceptors(yourHandshakeInterceptor)

Comment From: jasonrichdarmawan

@mschipperheyn

I'm not even clear on what header to supply to a stomp websocket message to get a Principal.

@rwinch Could this be a priority? It's been 5 years and the documentation is still not clear for WebSocket API with STOMP + Spring Session (in X-Auth-Token header instead of Cookie)

I am building the WebSocket API for mobile app, the default Cookie-based authentication is out of the option. The only option is to provide X-Auth-Token header in the STOMP CONNECT frame and use the X-Auth-Token to find the Principal.

I am having difficulty to get Principal by using the session Id from the X-Auth-Token header's value. I created a Feature Request in Spring Session