Describe the bug Prior to Spring Security 6, the CsrfTokenRepository used the response.addCookie in the saveToken method to add the XSRF-TOKEN cookie. In Spring-Security 6 it was changed to call response.addHeader which bypasses the Tomcat CookieProcessor.
To Reproduce I forked the Spring-Security-Samples project and used hello-security-explicit https://github.com/burghduffkc/spring-security-samples/commits/main/servlet/spring-boot/java/hello-security-explicit, below are the modifications and steps to reproduce.
- Add the following to the HttpSecurity in the SecurityFilterChain bean of the SecurityConfiguration class
.csrf((httpSecurityCsrfConfigurer -> {
//START Bug change
httpSecurityCsrfConfigurer
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringRequestMatchers(request -> Pattern.compile("^(GET)$").matcher(request.getMethod()).matches());
}))
- Add the following Bean to the SecurityConfiguration class
@Bean
WebServerFactoryCustomizer<TomcatServletWebServerFactory> servletWebServerFactoryWebServerFactoryCustomizer(){
return container -> container.addContextCustomizers(context -> {
Rfc6265CookieProcessor rfc = new Rfc6265CookieProcessor();
rfc.setSameSiteCookies("STRICT");
context.setCookieProcessor(rfc);
});
}
- run the spring boot application
- Open Chrome and the Chrome Developer tools and access
http://locahost:8080 - Look at the cookies under Application -> Storage -> Cookies. You will see that the
JSESSIONIDcookie has the sameSite set to Strict, but theXSRF-TOKENdoes not have sameSite set. This is because theCsrfTokenRepository#saveTokendoes not use addCookie, bypassing the Tomcat CookieProcessor.
Expected behavior A clear and concise description of what you expected to happen. The XSRF-TOKEN cookie should have sameSite set to Strict. Sample
Change to hello-security-explicit sample https://github.com/burghduffkc/spring-security-samples/commit/fb8971a5b035f694b10965924f2025095b283ba5
Full code for Spring-Security Example https://github.com/burghduffkc/spring-security-samples/commits/main/servlet/spring-boot/java/hello-security-explicit
A link to a GitHub repository with a minimal, reproducible sample.
Reports that include a sample will take priority over reports that do not. At times, we may require a sample, so it is good to try and include a sample up front.
Comment From: marcusdacoregio
Hi, @burghduffkc. Thanks for the report. I've successfully reproduced the error on my side. We are working on a fix.
Comment From: marcusdacoregio
For the time being, you can work around that by customizing the cookie generated by the CookieCsrfTokenRepository, like so:
var repository = CookieCsrfTokenRepository.withHttpOnlyFalse();
repository.setCookieCustomizer((customizer) -> {
customizer.sameSite(sameSitePolicy);
});
Comment From: burghduffkc
@marcusdacoregio Thank you for the suggestion, unfortunately that would require us to update all applications, as our current Tomcat CookieProcessor is configured in the context.xml file and not in Spring.
Example Configuration for context.xml
<Context>
<CookieProcessor className="org.apache.tomcat.util.http.Rfc265CookieProcessor" sameSiteCookes="strict" />
</Context>
Comment From: marcusdacoregio
Thanks, @burghduffkc. This is now merged into 6.1.x and main. It would be awesome if you could try 6.1.6-SNAPSHOT (the updated version will be available in a few minutes) and let us know if that is really fixed.
Comment From: burghduffkc
@marcusdacoregio I tested the snapshot and was able to verify the issue was fixed. Thanks for the quick turnaround!!!
Comment From: acutus
Hi,
It seems this fix might have broken backwards compatibility with jakarta servlet 5, as it uses the new Cookie#setAttribute()-method.
At least when using a cookieCustomizer(like mentioned in an earlier comment) to set SameSite-attribute, upgrading to spring-security-web:6.1.9causes the error below. Downgrading to spring-security-web:6.1.5 fixes the issue.
2024-11-26 16:24:18 java.lang.NoSuchMethodError: 'void jakarta.servlet.http.Cookie.setAttribute(java.lang.String, java.lang.String)'
2024-11-26 16:24:18 at org.springframework.security.web.csrf.CookieCsrfTokenRepository.mapToCookie(CookieCsrfTokenRepository.java:200)
@marcusdacoregio I assume this was unintentional and servlet 5 should be supported, but wanted to make sure before raising a new issue about this?
Comment From: marcusdacoregio
Hi @acutus, please go ahead and create a new ticket
Comment From: acutus
Will do
Comment From: acutus
Created https://github.com/spring-projects/spring-security/issues/16173