-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Expected Behavior
The Spring Session should authenticate session by getting the X-Auth-Token
header's value for the WebSocket endpoint. Currently, only REST endpoint that authenticates session if the X-Auth-Token
header is present.
Current Behavior
The Spring Session ignores the X-Auth-Token
header for the WebSocket endpoint in CONNECT frame. This issue causes every WebSocket connection to be anoymous.
e.g in REST endpoint
User send request to GET /helloworld with X-Auth-Token
header. The server recognize the token and return the response with body "Hello World"
e.g in WebSocket endpoint
- User send a HTTP handshake to GET /chat.
- User send a CONNECT frame with
X-Auth-Token
. But currently there is no way to retrieve the Principal from theX-Auth-Token
, so every request is an anonymousUser.
Client is written in JavaScript and use STOMP
let stompClient = null;
const stompConfig = {
brokerURL: "ws://localhost:8080/chat",
connectHeaders: {
"X-AUTH-TOKEN": X_Auth_Token,
},
};
stompClient = new StompJs.Client(stompConfig);
stompClient.activate();
The current Spring Session docs to override HttpSession implementation does not explain how to use the X-Auth-Token
for the WebSocket. In fact, because the Cookie-based authentication
is disabled after overriding the HttpSession implementation, there is no way to authenticate user for the WebSocket endpoint using the HttpSession.
To provide session in X-Auth-Token
header, you can override the HttpSession with an annotation
// see: https://docs.spring.io/spring-session/docs/current/reference/html5/#httpsession-rest
@Configuration
// Override HttpSession's Filter, in this instance Spring Session is backed by Redis.
@EnableRedisHttpSession
public class HttpSessionConfig {
// Default connection configuration, to localhost:6739.
@Bean
public LettuceConnectionFactory connectionFactory() {
return new LettuceConnectionFactory();
}
// Tell Spring to use HTTP headers, X-Auth-Token.
@Bean
public HttpSessionIdResolver httpSessionIdResolver() {
return HeaderHttpSessionIdResolver.xAuthToken();
}
}
Context
How has this issue affected you?
This is an issue because if you use annotation @EnableRedisHttpSession
both Browser and Mobile Apps can't authenticate when connecting to a WebSocket endpoint. By default, Spring Security provides you with Cookie-based authentication
and Spring can authenticate both for REST endpoint and WebSocket endpoint because the Cookie
e.g JSESSIONID
/ SESSION
and XSRF-TOKEN
is always there for each HTTP handshake, including the HTTP handshake for the WebSocket connection.
What are you trying to accomplish?
Get the Principal by using the X-Auth-Token
header's value
@Configuration
@EnableWebSocketMessageBroker
// see: https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#websocket-stomp-authentication-token-based
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
public class WebSocketAuthenticationConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(new ChannelInterceptor() {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor =
MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
String sessionId = accessor.getFirstNativeHeader("X-AUTH-TOKEN");
// accessor.setUser(user);
}
return message;
}
});
}
}
What other alternatives have you considered?
Use JWT
Are you aware of any workarounds?
As per my knowledge about HttpSession, currently there is no workarounds