title: JSON Web Token (JWT) with Spring based SockJS / STOMP Web Socket
body: <h1>Background</h1>
  
  <p>I am in the process of setting up a RESTful web application using Spring Boot (1.3.0.BUILD-SNAPSHOT) that includes a STOMP/SockJS WebSocket, which I intend to consume from an iOS app as well as web browsers. I want to use <a href="http://jwt.io">JSON Web Tokens</a> (JWT) to secure the REST requests and the WebSocket interface but I’m having difficulty with the latter.</p>
  
  <p>The app is secured with Spring Security:-</p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
  
      public WebSecurityConfiguration() {
          super(true);
      }
  
      @Autowired
      public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
          auth.inMemoryAuthentication()
                  .withUser("steve").password("steve").roles("USER");
      }
  
      @Override
      protected void configure(HttpSecurity http) throws Exception {
          http
              .exceptionHandling().and()
              .anonymous().and()
              .servletApi().and()
              .headers().cacheControl().and().and()
  
              // Relax CSRF on the WebSocket due to needing direct access from apps
              .csrf().ignoringAntMatchers("/ws/**").and()
  
              .authorizeRequests()
  
              //allow anonymous resource requests
              .antMatchers("/", "/index.html").permitAll()
              .antMatchers("/resources/**").permitAll()
  
              //allow anonymous POSTs to JWT
              .antMatchers(HttpMethod.POST, "/rest/jwt/token").permitAll()
  
              // Allow anonymous access to websocket 
              .antMatchers("/ws/**").permitAll()
  
              //all other request need to be authenticated
              .anyRequest().hasRole("USER").and()
  
              // Custom authentication on requests to /rest/jwt/token
              .addFilterBefore(new JWTLoginFilter("/rest/jwt/token", authenticationManagerBean()), UsernamePasswordAuthenticationFilter.class)
  
              // Custom JWT based authentication
              .addFilterBefore(new JWTTokenFilter(), UsernamePasswordAuthenticationFilter.class);
      }
  
  }
  </code></pre>
  
  <p>The WebSocket configuration is standard:-</p>
  
  <pre><code>@Configuration
  @EnableScheduling
  @EnableWebSocketMessageBroker
  public class WebSocketConfiguration extends AbstractWebSocketMessageBrokerConfigurer {
  
      @Override
      public void configureMessageBroker(MessageBrokerRegistry config) {
          config.enableSimpleBroker("/topic");
          config.setApplicationDestinationPrefixes("/app");
      }
  
      @Override
      public void registerStompEndpoints(StompEndpointRegistry registry) {
          registry.addEndpoint("/ws").withSockJS();
      }
  
  }
  </code></pre>
  
  <p>I also have a subclass of <code>AbstractSecurityWebSocketMessageBrokerConfigurer</code> to secure the WebSocket:-</p>
  
  <pre><code>@Configuration
  public class WebSocketSecurityConfiguration extends AbstractSecurityWebSocketMessageBrokerConfigurer {
  
      @Override
      protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
          messages.anyMessage().hasRole("USER");
      }
  
      @Override
      protected boolean sameOriginDisabled() {
          // We need to access this directly from apps, so can't do cross-site checks
          return true;
      }
  
  }
  </code></pre>
  
  <p>There is also a couple of <code>@RestController</code> annotated classes to handle various bits of functionality and these are secured successfully via the <code>JWTTokenFilter</code> registered in my <code>WebSecurityConfiguration</code> class.</p>
  
  <h1>Problem</h1>
  
  <p>However I can't seem to get the WebSocket to be secured with JWT. I am using <a href="https://github.com/sockjs/sockjs-client/releases/tag/v1.0.0">SockJS 1.1.0</a> and <a href="https://raw.githubusercontent.com/jmesnil/stomp-websocket/master/lib/stomp.js">STOMP 1.7.1</a> in the browser and can't figure out how to pass the token. It <a href="https://github.com/sockjs/sockjs-client/issues/196">would appear that</a> SockJS does not allow parameters to be sent with the initial <code>/info</code> and/or handshake requests.</p>
  
  <p>The <a href="http://docs.spring.io/autorepo/docs/spring-security/4.0.x/reference/html/websocket.html">Spring Security for WebSockets documentation states</a> that the <code>AbstractSecurityWebSocketMessageBrokerConfigurer</code> ensures that:</p>
  
  <blockquote>
    <p>Any inbound CONNECT message requires a valid CSRF token to enforce Same Origin Policy</p>
  </blockquote>
  
  <p>Which seems to imply that the initial handshake should be unsecured and authentication invoked at the point of receiving a STOMP CONNECT message. Unfortunately I can't seem to find any information with regards to implementing this. Additionally this approach would require additional logic to disconnect a rogue client that opens a WebSocket connection and never sends a STOMP CONNECT.</p>
  
  <p>Being (very) new to Spring I'm also not sure if or how Spring Sessions fits into this. While the documentation is very detailed there doesn't appear to a nice and simple (aka idiots) guide to how the various components fit together / interact with each other.</p>
  
  <h1>Question</h1>
  
  <p>How do I go about securing the SockJS WebSocket by providing a JSON Web Token, preferably at the point of handshake (is it even possible)?</p>