WebSockets
Spring Boot
403 Forbidden Error
Spring Security
Web Development

Websocket in Spring Boot app - Getting 403 Forbidden

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

A 403 Forbidden during WebSocket connection in Spring Boot usually means the HTTP handshake request was rejected before the socket upgraded. The root cause is commonly security configuration, origin checks, or missing endpoint registration alignment between client and server. Systematic checks quickly isolate the failure point.

Understand the Handshake Path

WebSocket starts as an HTTP request and then upgrades protocol. Any Spring Security rule that blocks that HTTP path will produce 403 before the socket exists. First confirm the exact endpoint and verify client and server paths match.

java
1@Configuration
2@EnableWebSocketMessageBroker
3public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
4    @Override
5    public void registerStompEndpoints(StompEndpointRegistry registry) {
6        registry.addEndpoint("/ws")
7                .setAllowedOriginPatterns("http://localhost:3000")
8                .withSockJS();
9    }
10
11    @Override
12    public void configureMessageBroker(MessageBrokerRegistry registry) {
13        registry.enableSimpleBroker("/topic");
14        registry.setApplicationDestinationPrefixes("/app");
15    }
16}

If the browser connects to /socket while server registers /ws, you may get status errors that look like security issues.

Align Spring Security Rules

Permit handshake endpoints explicitly in security config. If CSRF is enabled for all paths, SockJS handshake requests may fail unless configured correctly.

java
1@Bean
2SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
3    http
4        .csrf(csrf -> csrf.ignoringRequestMatchers("/ws/**"))
5        .authorizeHttpRequests(auth -> auth
6            .requestMatchers("/ws/**").permitAll()
7            .anyRequest().authenticated()
8        );
9    return http.build();
10}

In token based systems, ensure the same authentication mechanism is applied to the handshake and subsequent messaging flow. Inconsistent policy between these stages is a frequent cause of confusing failures.

Client Side Connection Checks

On the client, confirm the URL protocol, host, and port are correct for the deployment environment. For secure sites, use wss and valid certificates. Also check that reverse proxies forward upgrade headers.

javascript
1import { Client } from '@stomp/stompjs';
2
3const client = new Client({
4  brokerURL: 'ws://localhost:8080/ws',
5  reconnectDelay: 3000,
6  onConnect: () => console.log('connected'),
7  onStompError: frame => console.error(frame),
8});
9
10client.activate();

Server logs plus browser network traces together usually reveal whether the failure is authorization, CORS style origin policy, or proxy routing.

Proxy and Ingress Layer Checks

Many deployments place Spring Boot behind Nginx, Apache, or cloud ingress. Even with correct app config, missing upgrade headers in the proxy can block WebSocket handshake and produce status failures that look like authorization issues.

nginx
1location /ws {
2    proxy_pass http://app:8080;
3    proxy_http_version 1.1;
4    proxy_set_header Upgrade $http_upgrade;
5    proxy_set_header Connection "upgrade";
6    proxy_set_header Host $host;
7}

Verify that forwarded headers preserve original host and protocol information when your security logic depends on them. Keep one end to end integration test that opens a socket through the full production path so proxy regressions are caught before release.

A practical troubleshooting flow is: confirm endpoint path, confirm security permit rule, confirm allowed origins, then confirm proxy upgrade headers. Running this checklist in order prevents random trial and error edits and usually resolves handshake issues quickly.

For production reliability, expose a lightweight diagnostics endpoint that reports websocket broker health and recent handshake error counts. This gives operations teams fast visibility when connection failures spike after deployment.

Keep environment specific connection settings in one shared config module so client teams do not hard code different websocket URLs across applications. Centralized configuration reduces rollout mistakes when domains or ports change.

Common Pitfalls

  • Registering one endpoint path but connecting to another.
  • Blocking handshake path with strict security defaults.
  • Forgetting to configure allowed origins for browser based clients.
  • Using secure frontend origin with non secure websocket URL.
  • Missing proxy upgrade headers in production ingress layers.

Summary

  • Treat WebSocket 403 as handshake authorization or policy failure first.
  • Verify endpoint path, origin rules, and security permit rules.
  • Keep handshake and messaging authentication models consistent.
  • Inspect browser and server logs together for rapid diagnosis.
  • Validate proxy support for WebSocket upgrade in production.

Course illustration
Course illustration

All Rights Reserved.