Skip to main content
edited tags
Link
Source Link

How to access authenticated user principal in SessionConnectedEvent when using a ChannelInterceptor for JWT authentication?

I’m using a custom WebSocketChannelInterceptor (implements ChannelInterceptor) to handle authentication during the CONNECT STOMP command. The interceptor extracts and validates a JWT token from the Authorization header like this:

@Override public Message<?> preSend(@NonNull Message<?> message, @NonNull MessageChannel channel) { var accessor = StompHeaderAccessor.wrap(message); StompCommand command = accessor.getCommand(); if (command == null) { return null; } return switch (command) { case CONNECT -> handleConnect(message, accessor); case SEND -> handleSend(message, accessor); default -> message; }; } private Message<?> handleConnect(Message<?> message, StompHeaderAccessor accessor) { String authorizationHeader = accessor.getFirstNativeHeader(HttpHeaders.AUTHORIZATION); if (authorizationHeader == null || !authorizationHeader.startsWith(JwtService.BEARER_PREFIX)) { throw new MessageHandlingException(message, "Missing or invalid authorization header"); } String token = authorizationHeader.substring(JwtService.BEARER_PREFIX.length()).trim(); try { var jwtAuthToken = new JwtAuthenticationToken(token); authManager.authenticate(jwtAuthToken); return message; } catch (BadCredentialsException e) { throw new MessageHandlingException(message, e.getMessage()); } catch (RuntimeException e) { throw new MessageHandlingException(message, "Internal server error"); } } 

My question is: How can I access the authenticated user's Principal inside the SessionConnectedEvent handler?

@Slf4j @Component @RequiredArgsConstructor public class WebSocketEventListener { @EventListener public void sessionConnectedEvent(SessionConnectedEvent event) { // How to get Principal here? } } 

I’m not interested in SessionConnectEvent — I specifically want to get the user from SessionConnectedEvent after the handshake and connection are completed.

Thanks in advance!

I've tried many different approaches, but none of them worked for my case. The token is sent during the initial WebSocket connection using STOMP headers like this:

const client = new Client({ brokerURL: 'ws://localhost:8080/ws', connectHeaders: { "Authorization": `Bearer ${accessToken}`, }, onStompError: await onStompError, onConnect: () => { console.log("Successfully connected"); }, debug: console.debug });