spring-projects / spring-security

Spring Security
http://spring.io/projects/spring-security
Apache License 2.0
8.82k stars 5.9k forks source link

CSRF check on websockets not skipped if there is a Bearer token present. #15312

Closed ionutbarau closed 4 months ago

ionutbarau commented 4 months ago

I have a project composed of spring-cloud-gateway in front of a couple of spring boot microservices that use websockets. For authentication/authorization I use spring-authorization-server (OIDC/OAuth 2). I am trying to implement security in the gateway, including CSRF, however for websockets there seems to be an issue on how CSRF is handled.

Since the microservices are resource servers, when http request are sent from gateway to downstream services, CSRF check is skipped, as it finds the Bearer token, essentially trusting the gateway, as there is no cookie involved. See this for a good explanation. However, this does not happen for websocket endpoints. When using @EnableWebSocketSecurity, the CSRF token coming from the gateway is checked against the microservice token repo, which, of course will throw Invalid token exception.

Shouldn't websockets CSRF check be skipped if there is a Bearer token, just like regular http calls?

Is this intended behavior?

I have also posted here on SO about this topic.

As a workaround I have disabled CSRF by not using @EnableWebSocketSecurity. I have implemented authorization at gateway level so only authenticated users with specific oauth scope can call the connect endpoint. This could leave the service vulnerable if called directly. I have also used allowedOrigins to allow only specific clients to call the connect endpoint. I have posted here why I think it is enough and CSRF token might not be needed if we check the origin on the server.

sjohnr commented 4 months ago

@ionutbarau thanks for reaching out. However, it is not necessary to cross-post questions here as the team regularly reviews Stack Overflow.

Configuring a downstream application (e.g. a resource server) using http.oauth2ResourceServer() is only configuring authentication for HTTP requests and does not affect websockets. If you have an area of the documentation that you feel is misleading or missing, please let me know and we can open an issue to address that.

I have implemented authorization at gateway level so only authenticated users with specific oauth scope can call the connect endpoint. This could leave the service vulnerable if called directly.

I'm not clear what you mean by this? Note that CSRF protection protects users (not applications) when the browser can automatically provide credentials (e.g. session cookie, basic auth, etc.) to the server, which doesn't seem to be the case for your downstream service. I would recommend clarifying on the stackoverflow question what your concern is here.

Regardless, I'm going to close this question in favor of the stackoverflow question.