Search code examples
javaspringspring-securitywebsocketoauth

Secure Websocket connections with OAuth in Spring Boot app


I am going to add a WebSocket handler to my Spring Boot 3 application. But along with that, I want to secure it with OAuth. There is an already prepared authorization server for that. The important thing is that I want to use pure WebSocket instead of STOMP, so I will use @EnableWebSocket instead of @EnableWebSocketMessageBroker because I don't need all that complexity and functionality that broker-backed messaging over WebSocket introduces.

The questions is: How can OAuth validation be implemented in this case? Should I implement an interceptor? Should I perform the validation during handhsake? Looks like @EnableWebSocketSecurity is not suitable for this case, since it's acceptable when you use broker-backed messaging over WebSocket.


Solution

  • The solution is quite simple but requires some explanations, so I had to write a small article about that. I will attach the link at the end. Here, I will try to explain in short.

    First important thing

    If we are using pure WebSocket connections, there is a handshake process that is performed before a WebSocket connection is set up. The handshake is performed using HTTP/HTTPS (depending on your settings). After the handshake is performed, the connection is switched to WebSocket.

    Second important thing

    Since the handshake is performed using HTTP/HTTPS, we can cover the security needs with the usual security configuration that we use to secure endpoints. Security changes will be executed during the handshake. If the security validation is not passed, the handshake will fail and the WebSocket connection will not be set up.

    Necessary dependencies

    Except for the WebSocket dependency, we need only the usual security dependency and the dependency to connect to the OAuth authorization server:

     implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
     implementation 'org.springframework.boot:spring-boot-starter-security'
     implementation 'org.springframework.boot:spring-boot-starter-websocket'
    

    Configuration

    In the configuration, we just set up OAuth server validation and describe security rules for the desired endpoint.

    @Configuration
    public class WebSecurityConfig {
    
        @Bean
        public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
            return http
                    .authorizeHttpRequests(registry -> registry
                            .requestMatchers("/websocket/endpoint").hasAuthority("SCOPE_my.scope")
                    )
                    .oauth2ResourceServer(configurer -> configurer
                            .jwt(withDefaults())
                    )
                    .build();
        }
    
    }
    

    OAuth properties

    In the application properties file we need to set up properties for our connections to the authorization server. In my case the server is located on http://auth-server:9000.

    spring:
      security:
        oauth2:
          resourceserver:
            jwt:
              issuer-uri: http://auth-server:9000
    

    And that's it. Now, during the handshake, the described security rules will be applied. The described application properties will be used during the connection to the authorization server. When the handshake is performed, the WebSocket connection will be set up.

    Full article

    Link to the article (step-by-step guide): https://medium.com/@HereAndBeyond/bf479327339f