Skip to content

Add support for Session in X-Auth-Token header for WebSocket endpoint, currently only REST endpoint is supported by X-Auth-Token header #1784

@jasonrichdarmawan

Description

@jasonrichdarmawan

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

  1. User send a HTTP handshake to GET /chat.
  2. User send a CONNECT frame with X-Auth-Token. But currently there is no way to retrieve the Principal from the X-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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions