title: How to secure websocket application [Spring boot + STOMP]
body: <p>Good morning,</p>
  
  <p>I've created a simple Spring Boot WebSocket application. Right now I would like to set some security to it. I've trying some examples but I cannot get it worked. I'm getting error:</p>
  
  <p><em>web browser:</em></p>
  
  <pre><code>&gt;&gt;&gt; CONNECT
  ${_csrf.headerName}:${_csrf.token}
  accept-version:1.1,1.0
  heart-beat:10000,10000
  
  &lt;&lt;&lt; ERROR
  message:Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is org.springframework.security.web.csrf.MissingCsrfTokenException\c Could not verify the provided CSRF token because your session was not found.
  content-length:0
  </code></pre>
  
  <p><em>Log in STS:</em></p>
  
  <pre><code>Failed to send client message to application via MessageChannel in session cc25e1mw. Sending STOMP ERROR to client.
  </code></pre>
  
  <p><em>StackTrace:</em></p>
  
  <pre><code>org.springframework.messaging.MessageDeliveryException: Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is org.springframework.security.web.csrf.MissingCsrfTokenException: Could not verify the provided CSRF token because your session was not found.
  at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:127) ~[spring-messaging-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:104) ~[spring-messaging-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.web.socket.messaging.StompSubProtocolHandler.handleMessageFromClient(StompSubProtocolHandler.java:299) ~[spring-websocket-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.handleMessage(SubProtocolWebSocketHandler.java:306) [spring-websocket-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75) [spring-websocket-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56) [spring-websocket-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.handleMessage(ExceptionWebSocketHandlerDecorator.java:58) [spring-websocket-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.delegateMessages(AbstractSockJsSession.java:380) [spring-websocket-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession.handleMessage(WebSocketServerSockJsSession.java:194) [spring-websocket-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.web.socket.sockjs.transport.handler.SockJsWebSocketHandler.handleTextMessage(SockJsWebSocketHandler.java:92) [spring-websocket-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.web.socket.handler.AbstractWebSocketHandler.handleMessage(AbstractWebSocketHandler.java:43) [spring-websocket-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:110) [spring-websocket-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access$000(StandardWebSocketHandlerAdapter.java:42) [spring-websocket-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:81) [spring-websocket-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:78) [spring-websocket-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:395) [tomcat-embed-websocket-8.5.23.jar:8.5.23]
  at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageText(WsFrameServer.java:119) [tomcat-embed-websocket-8.5.23.jar:8.5.23]
  at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495) [tomcat-embed-websocket-8.5.23.jar:8.5.23]
  at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294) [tomcat-embed-websocket-8.5.23.jar:8.5.23]
  at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) [tomcat-embed-websocket-8.5.23.jar:8.5.23]
  at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82) [tomcat-embed-websocket-8.5.23.jar:8.5.23]
  at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171) [tomcat-embed-websocket-8.5.23.jar:8.5.23]
  at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151) [tomcat-embed-websocket-8.5.23.jar:8.5.23]
  at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) [tomcat-embed-websocket-8.5.23.jar:8.5.23]
  at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) [tomcat-embed-core-8.5.23.jar:8.5.23]
  at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) [tomcat-embed-core-8.5.23.jar:8.5.23]
  at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.23.jar:8.5.23]
  at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.23.jar:8.5.23]
  at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.23.jar:8.5.23]
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_144]
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_144]
  at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.23.jar:8.5.23]
  at java.lang.Thread.run(Thread.java:748) [na:1.8.0_144]
  Caused by: org.springframework.security.web.csrf.MissingCsrfTokenException: Could not verify the provided CSRF token because your session was not found.
  at org.springframework.security.messaging.web.csrf.CsrfChannelInterceptor.preSend(CsrfChannelInterceptor.java:55) ~[spring-security-messaging-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  at org.springframework.messaging.support.AbstractMessageChannel$ChannelInterceptorChain.applyPreSend(AbstractMessageChannel.java:158) ~[spring-messaging-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:113) ~[spring-messaging-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  ... 32 common frames omitted
  </code></pre>
  
  <p>My configuration files:</p>
  
  <p><em>WebSocketConfig</em></p>
  
  <pre><code>@Configuration
  @EnableWebSocketMessageBroker
  public class WebSocketConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer{
  
  
  
  @Override
  public void configureMessageBroker(MessageBrokerRegistry config) {
      config.enableSimpleBroker("/topic");
      config.setApplicationDestinationPrefixes("/app");
  }
  
  @Override
  public void registerStompEndpoints(StompEndpointRegistry registry) {
      registry.addEndpoint("/websocket").setHandshakeHandler(new MyHandshakeHandler()).setAllowedOrigins("*").withSockJS();
  }
  
  public class MyHandshakeHandler extends DefaultHandshakeHandler {
  
      @Override
      protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler,
              Map&lt;String, Object&gt; attributes) {
          // TODO Auto-generated method stub
          return super.determineUser(request, wsHandler, attributes);
      }
  
  
  }
  }
  </code></pre>
  
  <p><em>Controller function</em></p>
  
  <pre><code>@MessageMapping("/hello")
  @SendTo("/topic/messaging")
  public Message sendMessage(Message message) throws Exception {
      Thread.sleep(10); // simulated delay
      messageRepository.save(message);
  
      return new Message(message.getFromUserId(), message.getToUserId(), message.getMessageText(), "delivered", message.getDate());
  }
  </code></pre>
  
  <p><em>JS function to connect:</em></p>
  
  <pre><code>function connect() {
  var headerName = "${_csrf.headerName}";
  var token = "${_csrf.token}";
  var headers = {};
  headers[headerName] = token;
  
  var socket = new SockJS('/websocket');
  stompClient = Stomp.over(socket);
  stompClient.connect(headers, function (frame) {
      setConnected(true);
      console.log('Connected: ' + frame);
      stompClient.subscribe('/topic/messaging', function (message) {
          showMessage(JSON.parse(message.body).messageText);
      });
  });
  }
  </code></pre>
  
  <p>So my problem is: web browser is connecting to application and send message (I dont know if it is secured) but it cannot receive any message from application.</p>
  
  <p>My question: How to achive secured websocket connection, and how to get rid of that error.</p>
  
  <p>I'm new to securing web application so please be forgiving.</p>
  
  <p>Thank You for any advice.</p>
  
  <p>Andrew</p>