How to authenticate WebSocket within an existing HTTP environment with Spring Security

844 views Asked by At

I have a pretty simple requirement (I use Spring-Security 4.0.1) but I can't find any examples on the web except what is been told on this page: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html#websocket-server-handler

It is relatively simple to integrate a WebSocketHandler into other HTTP serving environments with the help of WebSocketHttpRequestHandler.

What I have: An implementation of WebSocketHandler that does the job and an HTTP serving environments using a Basic Authentication. My WebApplicationInitializer looks like this:

public class MyWebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        ...
        // WebSocket support - Handshake
        Dynamic ws = servletContext.addServlet("webSocketHttpRequestHandler", new HttpRequestHandlerServlet());
        ws.addMapping("/streaming/*");

        // Spring Security Filter
        FilterRegistration.Dynamic springSecurity = servletContext.addFilter("springSecurityFilterChain", new DelegatingFilterProxy());
        springSecurity.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
    }
}

This is how I plugged my websocket endpoint to my existing web application. My WebSocket configuration class looks like (very simplified) this:

@Configuration
public class WebSocketServicesConfig{
    @Bean
    public WebSocketHttpRequestHandler webSocketHttpRequestHandler() {
        return new WebSocketHttpRequestHandler(new StreamingWebSocketHandler());
    }
}

StreamingWebSocketHandler implements WebSocketHandler.

I also have a RESTful Web Service (in the same server) that uses the configured Basic Authentication.

What is working: My RESTful Web Service is working with any web browsers. I can do some authenticated queries (credentials can be sent in the HTTP headers). WebSocket queries are working and ask for authentication the first time I try to do some (under FireFox, a popup appears asking for credentials, once I enter them, client and server are able to communicate via WebSocket messages). In my WebSocketHandler, the Spring object: WebSocketSession that contains informations about the authenticated user is correct (#getPrincipal() method returns a Authentication containing the right granted Authorities, details and so on...). Note that once the websocket is authenticated, I can relaunch the query without re-enter them.

What I want: On a user point of view, this is bad because the credentials are required twice:

  1. First for RESTful queries
  2. Second for WebSocket queries

How can I bypass the second authentication assuming the first one succeeded? Is there a way to detect the client has been authenticated and not ask for credentials?

What I don't want: I don't want to use neither Stomp over websocket nor SockJs (I don't need to support old web browsers).

0

There are 0 answers