Describe the bug
When configuring WebSocket message security via Spring Security's XML support, a CsrfChannelInterceptor
is configured but the default CSRF handler in the web layer is generated by the XorCsrfTokenRequestAttributeHandler
, so STOMP CONNECT
messages that present the XOR'd CSRF value are rejected as a mismatch.
To Reproduce Configure WebSocket security via XML with basic defaults, for example:
<websocket-message-broker>
<intercept-message type="CONNECT" access="permitAll" />
<intercept-message type="UNSUBSCRIBE" access="permitAll" />
<intercept-message type="DISCONNECT" access="permitAll" />
<intercept-message pattern="/pub/**" access="permitAll" />
<intercept-message pattern="/**" access="hasRole('USER')" />
</websocket-message-broker>
When a client that has authenticated successfully with Spring Security tries to issue a STOMP CONNECT
request, passing in the active session-based CSRF value generated by Spring Security's .web.csrf.XorCsrfTokenRequestAttributeHandler
the message is rejected and the connection terminated.
Expected behavior
I thought Spring Security 6 could switch to defaulting to .messaging.web.csrf.XorCsrfChannelInterceptor
now instead of .messaging.web.csrf.CsrfChannelInterceptor
, in WebSocketMessageBrokerSecurityBeanDefinitionParser e.g.
if (!this.sameOriginDisabled) {
interceptors.add(new RootBeanDefinition(XorCsrfChannelInterceptor.class));
}
Work-around
I couldn't find a simple way to use XorCsrfChannelInterceptor
so I added a basic BeanPostProcessor
to my application that replaced the CsrfChannelInterceptor
instance with an XorCsrfChannelInterceptor
instance on the ExecutorSubscribableChannel
bean.