I’m building a WebSocket-based microservice architecture using Spring Cloud Gateway and STOMP WebSockets.
Users log in through the frontend, and the backend sets:
access_token(HttpOnly, Secure, SameSite)refresh_token(HttpOnly)
The frontend cannot read these cookies (as expected).
Everything works fine for normal HTTP requests — the HttpOnly cookies are automatically sent with each request to the gateway.
🚨 Problem
When I try to connect to the WebSocket endpoint:
const client = new Client({
webSocketFactory: () => new WebSocket('ws://localhost:8090/ws-chat'),
connectHeaders: {
Cookie: `access_token=${TOKEN}` // <-- this is impossible in real browser
}
});
Cookie is always null on the backend gateway:
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
System.out.println(exchange.getRequest().getCookies());
// Result: {}
};
}
Because the frontend cannot access HttpOnly cookies, I cannot attach the access token to the WebSocket handshake request.
So inside my gateway filter this fails:
String accessToken = request.getCookies().getFirst("access_token").getValue();
// access_token is null => NullPointerException
❓ Question
How do real apps like WhatsApp, Telegram, etc. handle WebSocket authentication when the token is stored in HttpOnly cookies and the frontend cannot read it?
Specifically:
How can I securely authenticate WebSocket connections through the gateway?
How can I pass authentication data during
CONNECThandshake when browser JS cannot read cookies?Is there a pattern (e.g., temporary WS token, session handshake, etc.) that I should implement?