My goal is to authenticate the WebSocket CONNECT frame. I wish to be able to initialize Authentication user = ...
by using X-Auth-Token
.
TL:DR
I use the X-Auth-Token
header. How the current authentication works:
- User hit POST
/login
endpoint with Form Data username
and password
.
- The response header will contain the key
X-Auth-Token
.
- If you hit any REST endpoint with
X-Auth-Token
the server will recognize the user.
- The issue is how to get Authentication from
X-Auth-Token
in the WebSocket CONNECT frame.
The current solution is to use JWT, however, one of the requirements for this project is a user should be able to invalidate the session. For JWT to be able to do that, the JWT should be a stateful, reference to this SO's the question
@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");
// Authentication user; // How to get Authentication from X-Auth-Token?
// accessor.setUser(user);
}
return message;
}
});
}
}
What I did:
- I change
Cookie-based authentication
by letting the session be provided in a header.
// 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();
}
}
- logic to CONNECT and SUBSCRIBE
const X-Auth-Token = "" // get from the POST `/login` endpoint
const onConnectCallback = () => {
const destinations = ["/topic/channel/1", "/user/queue/messages"];
for (let i = 0; i < destinations.length; i++) {
stompClient.subscribe(destinations[i], (payload) => {
// receiveMessageCallback
});
}
};
const stompConfig = {
brokerURL: "ws://localhost:8080/chat",
connectHeaders: {
"X-Auth-Token": X_Auth_Token,
},
onConnect: onConnectCallback,
};
const stompClient = new StompJs.Client(stompConfig);
stompClient.activate();
Reference
I am worried that X-Auth-Token
is not supported in WebSocket because based on SO's answer there is no API to retrieve session by id
question from:
https://stackoverflow.com/questions/65930974/how-to-get-authentication-from-x-auth-token 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…