javaspringspring-websocketstompbad-request

Spring WebSocket upgrade failure. response 400 BAD_REQUEST


I have an Spring app with Stomp WebSocket but when i try to connect to it using Postman or wscat i get an "error : Unexpected server response : 400"

Here is configurating code i use :

In WebSocketConfig

@Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        System.out.println("Registering Stomp Endpoints");
        try {
            registry.addEndpoint("/chat-service")
                    .setAllowedOrigins("*")
                    .addInterceptors(new HandshakeDebugInterceptor())
                    .withSockJS();
            System.out.println("Stomp Endpoints Registered Successfully");
        } catch (Exception e) {
            System.out.println("Error registering Stomp Endpoints: " + e.getMessage());
        }
    }

In SecurityConfiguration

@Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(AbstractHttpConfigurer::disable)
                .cors(Customizer.withDefaults())
                .authorizeHttpRequests((authorize) -> {
                            authorize
                                    .requestMatchers("/api/auth/*").permitAll()
                                    .requestMatchers("/chat-service/**").permitAll()
                                    .requestMatchers("/admin/**").hasRole("ADMIN")
                                    //.anyRequest().authenticated();
                                    .anyRequest().permitAll();
                        }
                )
                .sessionManagement((configurer) -> {
                    configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
                })
                .authenticationProvider(authenticationProvider)
                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
                .logout(Customizer.withDefaults()
                );

                http.addFilterBefore((request, response, chain) -> {
                    HttpServletRequest httpRequest = (HttpServletRequest) request;
                    HttpServletResponse httpResponse = (HttpServletResponse) response;
                    System.out.println("Request to: " + httpRequest.getRequestURI());
                    System.out.println("Method: " + httpRequest.getMethod());
                    System.out.println("Headers: " + httpRequest.getHeaderNames());
                    System.out.println("User Principal: " + httpRequest.getUserPrincipal());
                    System.out.println("Authentication: " + SecurityContextHolder.getContext().getAuthentication());
                    chain.doFilter(httpRequest, httpResponse);
                }, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

All another endpoints like register or login works correctly I added a lot of logging in securityFilterChain and OncePerRequestFilter filter but i can find any usefull information what cause a 400 response.

Here is logs from server when i run ( same response for http:// and for ws:// )

wscat -c ws://localhost:8081/chat-service
  : Securing GET /chat-service
Request to: /chat-service
Method: GET
Headers: org.springframework.security.web.firewall.StrictHttpFirewall$StrictFirewalledRequest$2@5118325e
User Principal: null
Authentication: null
2024-04-01T21:11:26.365+03:00 DEBUG 21456 --- [messenger] [nio-8081-exec-7] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
2024-04-01T21:11:26.366+03:00 DEBUG 21456 --- [messenger] [nio-8081-exec-7] o.s.security.web.FilterChainProxy      
  : Secured GET /chat-service
2024-04-01T21:11:26.367+03:00  INFO 21456 --- [messenger] [nio-8081-exec-7] c.m.m.c.RequestResponseLoggingFilter   
  : Request: GET /chat-service
2024-04-01T21:11:26.367+03:00 DEBUG 21456 --- [messenger] [nio-8081-exec-7] o.s.web.servlet.DispatcherServlet      
  : GET "/chat-service", parameters={}
2024-04-01T21:11:26.368+03:00 DEBUG 21456 --- [messenger] [nio-8081-exec-7] o.s.web.servlet.DispatcherServlet      
  : Completed 400 BAD_REQUEST
2024-04-01T21:11:26.369+03:00  INFO 21456 --- [messenger] [nio-8081-exec-7] c.m.m.c.RequestResponseLoggingFilter   
  : Response: 400 null


Solution

  • So, I increase level of logging and enable TRACE in application.properties for whole .web and i get some interesting result in logs :

    2024-04-02T13:07:02.461+03:00 TRACE 9164 --- [messenger] [nio-8081-exec-1] o.s.w.s.s.s.WebSocketHandlerMapping     
     : Mapped to HandlerExecutionChain with [org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler@3c1afe71] and 1 interceptors
    2024-04-02T13:07:02.477+03:00 DEBUG 9164 --- [messenger] [nio-8081-exec-1] o.s.w.s.s.t.h.DefaultSockJsService      
     : Processing transport request: GET http://localhost:8081/chat-service
    2024-04-02T13:07:02.479+03:00 TRACE 9164 --- [messenger] [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet       
     : No view rendering, null ModelAndView returned.
    2024-04-02T13:07:02.482+03:00 DEBUG 9164 --- [messenger] [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet       
     : Completed 400 BAD_REQUEST, headers={masked}
    2024-04-02T13:07:02.485+03:00  INFO 9164 --- [messenger] [nio-8081-exec-1] c.m.m.c.RequestResponseLoggingFilter    
    

    Before DispatcherServlet 400 response was some logs from SockJS so, I removed .withSockJS() from WebSocketConfig and now I can connect to my app from postman or wscat, but I think this thing must be brought back when client for application will be ready.