Skip to content
Advertisement

Why I can StompCommand.CONNECT without JSESSIONID, but X-XSRF-TOKEN is required?

My goal is to secure a WebSocket endpoint e.g ws://localhost:8080/chat.

What I did:

  1. I tried to create WebSocket connection with STOMP

    JavaScript

    AbstractSecurityWebSocketMessageBrokerConfigurer

    JavaScript

    WebSocketMessageBrokerConfigurer

    JavaScript

    WebSecurityConfigurerAdapter

    JavaScript

My expected result is: The WebSocket connection should fail because I did not send the JSESSIONID.

My actual result is: The Spring Security recognize the user, and I can get the UserDetails with (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal().

My questions:

  1. If I wish to use Database, which should I store, the JSESSIONID or the XSRF-TOKEN ?

  2. Is using X-XSRF-TOKEN the right way to secure StompCommand.CONNECT endpoint?

  3. Why the Spring Security ask for X-XSRF-TOKEN instead of JSESSIONID. Isn’t CSRF token used to prevent Cross-Site Request Forgery?

    This is the error I get from the Browser’s console if I create a WebSocket connection without X-XSRF-TOKEN‘s key in the request header.

    JavaScript

Advertisement

Answer

First, I will try to help you with WS connection. I tried configuration similar to yours and I was unable to connect to WS unauthorized. I confirmed that in browser there was no JSESSIONID cookie or when there was one, it was connected to anonymous session. Try setting logging of org.springframework.security to TRACE and follow written log, it will help you determine which filter authorised access, if that is the case.

For questions that you specified:

  1. JSESSIONID and XSRF-TOKEN are not something that are interchangeable. I believe that for same JSESSIONID you can receive different different XSRF-TOKEN cookies. So I think you should store session id. Spring has project for this: Spring Session JDBC

  2. I think that it is. Even Spring Security expects it by default. Spring Security Websocket

Any inbound CONNECT message requires a valid CSRF token to enforce Same Origin Policy

  1. I am not sure how familiar are you with the Cross-Site Request Forgery. If you are not, check this Spring CSRF, but in few sentences:

JSESSIONID is cookie and it will be sent with every request to your site, even from other sites. Because that is how browser works. So to prevent misusage of session, CSRF token is required. Because you are not using HTML to execute action, such as form submit, you need to pass this token some other way. Spring requires you to send it using Header named X-XSRF-TOKEN, because browser will not send it with every request like it would a cookie. Security is in that other site, which tries to exploit vulnerability, can not read cookie from your site and it can not use it to add CSRF in header for exploit request.

So, I think your solution is ok. Keep in mind, that HTTP and WS are different protocols, even if WS uses HTTP for handshake, but it adds multiple headers. Maybe because of that Spring ignores authority checks, but I think that you probably missed something and that spring security trace log will direct you what to check.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement