Currently, there's no way from application.properties
to configure the Spring Session session cookie's SameSite
attribute. It would be nice to be able to do that.
For consistency with the existing server.servlet.session.cookie
properties, I suggest:
server.servlet.session.cookie.sameSite
with a default value of "Lax" (to match Spring Session 2.1's behavior defined in DefaultCookieSerializer). A value of empty string would map to null
(which results in DefaultCookieSerializer
not setting the SameSite
attribute on the cookie).
SessionAutoConfiguration would implement this behavior.
This setting would have no effect when Spring Session is not in use as no servlet containers currently expose a means by which to set the SameSite
attribute on their session cookies (support for that can be added as containers gain that ability).
Note that this is likely to be increasingly used as the default session cookie in Spring Session 2.1 has the attribute SameSite=Lax
(see https://github.com/spring-projects/spring-session/issues/1005) which breaks SAML login, so anyone using SAML (such as via Spring Security SAML) is going to have to need to change this configuration:
https://groups.google.com/a/chromium.org/d/msg/security-dev/AxY6BpkkH9U/vgKbDm7rFgAJ
As a further enhancement, perhaps if Spring Security SAML is detected, server.servlet.session
can be set to null by default instead of "Lax".
Comment From: philwebb
This looks like a sensible addition, but I'd rather scope it specifically to Spring Session rather than make it a general feature. I've no idea if/when javax.servlet.http.Cookie
will get the equivalent support and if feels a bit odd that a server.servlet.session.samesite
property would just be ignored.
I think we should add it under spring.session.cookie.samesite
and probably offer an enum with OFF
, STRICT
and LAX
as values.
Comment From: mbhave
I don't know if it makes sense to just make the sameSite
attribute configuration for Spring Session. There are other things that can be configured such as cookieMaxAge
etc and we don't have configuration properties for those either under SessionProperties
.
Comment From: philwebb
Oh yeah :(
Actually, I'm a little confused as to how you change the sameSite
attribute at all. The org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration
class seems to create a DefaultCookieSerializer
then call setters from javax.servlet.SessionCookieConfig
. I guess we currently rely on that.
Looks like we'd need to register a CookieSerializer
as a bean and do that createDefaultCookieSerializer
work ourselves.
Comment From: philwebb
This is turning out to be a bigger feature than just Spring Session I think. We'll need to look across the board at how we should support the option.
Some relevant links:
- https://github.com/spring-projects/spring-framework/commit/09d9450154be796349dabdc606ade57beae08724
- https://github.com/netty/netty/issues/6509
- http://mail-archives.apache.org/mod_mbox/tomcat-dev/201806.mbox/%3Cb5cf92e1-01d0-8dff-7a72-6a5080d46543@apache.org%3E
- https://issues.jboss.org/browse/UNDERTOW-1024
- https://github.com/undertow-io/undertow/commit/c40847e196665f65808cfeb7bce1ceaa3e510c04
Comment From: vpavic
I can chime in with Spring Session side of things regarding SameSite
cookie attribute, and everything around it which might be relevant from the perspective of extending the Spring Session auto-configuration support.
In Spring Session's HttpSession
(i.e. Servlet) integration, there is a concept of HttpSessionIdResolver
, which is the strategy for correlating incoming HTTP request to session - by default, a cookie based implementation (CookieHttpSessionIdResolver
) is used while we also offer header based implementation (HeaderHttpSessionIdResolver
) out of the box.
With cookie based implementation, the concept of CookieSerializer
comes into play as well. This is the component that's responsible for writing the session cookie, and which the SameSite
related configuration property would ultimately be mapped to.
I'm describing all this to make it clear that any extension of Spring Boot's auto-configuration support for Spring Session as requested here would likely have to consider both HttpSessionIdResolver
and CookieSerializer
.
Spring Session's configuration facilities try to be customization friendly by doing the following things:
- if user registers a bean of type HttpSessionIdResolver
, we pick it up and use instead of the default cookie based one
- if user registers a bean of type CookieSerializer
, we pick it up and configure the default cookie based HttpSessionIdResolver
to use it
- we try to configure the default CookieSerializer
based on SessionCookieConfig
So one can customize the SameSite
attribute of session cookie registering DefaultCookieSerializer
bean with DefaultCookieSerializer#setSameSite
set to null
(or even go a step further and register the desirable HttpSessionIdResolver
bean).
Having said that, the proposed server.servlet.session.samesite
doesn't really make sense, as SameSite
is cookie related and therefore any property related to it should sit under server.servlet.session.cookie
namespace. However, since server.servlet.session.cookie
actually maps SessionCookieConfig
this would be confusing as Servlet API provides no SameSite
support at the moment.
For reactive side of the things, the entire story is completely out of Spring Session's scope as WebSessionIdResolver
(which is the equivalent of Spring Session's HttpSessionIdResolver
) is actually a part of Spring WebFlux.
Considering that Spring Session's configuration is fairly simple to customize on its own, as well as the complexity the would be required to add to auto-configuration support in Spring Boot (and which would in big part duplicate what Spring Session's own configuration already offers on its own), and that there's no support for SameSite
attribute in Servlet API, I'd recommend against making any changes. If Servlet API catches up in some future release and adds support for SameSite
, the problem will solve itself as we on Spring Session side would pick up the new property from SessionCookieConfig
and configure the default serializer accordingly.
Comment From: candrews
Can we add a SameSite
property (the type being an enum having values for lax, strict, and none, defaulting to lax) to SessionCookieConfig
now, but have it not do anything for session implementations that don't support the SameSite attribute?
Right now, it's supportable for Spring Session. Support can be added for base servlet, WebFlux, etc as those packages gain SameSite support.
Comment From: vpavic
SessionCookieConfig
is a Servlet API thing.
Comment From: candrews
Sorry, I meant org.springframework.boot.web.servlet.server.Session.Cookie
(again, my apologies for the mistake). The point I was making is that support for what can be supported can be done now without having to wait until javax.servlet.SessionCookieConfig
is updated with SameSite support.
Comment From: wilkinsona
That comes back to @vpavic's earlier point which I agree with:
However, since
server.servlet.session.cookie
actually mapsSessionCookieConfig
this would be confusing as Servlet API provides no SameSite support at the moment.
I wouldn't want a general server.servlet.*
property to only work when you're using Spring Session or only work when you're using a particular embedded container.
Comment From: candrews
Even if the intent is to work with the servlet spec when it's updated, meaning this would be a temporary situation?
Comment From: wilkinsona
Yes as things would be confusing in the interim. Furthermore, there’s no guarantee that it would be temporary as the Servlet spec is out of our control.
Comment From: philwebb
Considering that Spring Session's configuration is fairly simple to customize on its own, as well as the complexity the would be required to add to auto-configuration support in Spring Boot (and which would in big part duplicate what Spring Session's own configuration already offers on its own), and that there's no support for SameSite attribute in Servlet API, I'd recommend against making any changes.
I'm inclined to agree. I'm going to close this one for now and wait to see how any Servlet API spec changes work out.
Comment From: vpavic
Given this was declined, it seems that 2.2.x
milestone was left on by mistake.
Comment From: OrangeDog
As well as SAML, it appears the defaults also make it impossible to use Access-Control-Allow-Credentials
.
For others looking for property-based configuration, simply add this bean.
@Bean
@ConfigurationProperties("spring.session.cookie")
public DefaultCookieSerializer cookieSerializer() {
return new DefaultCookieSerializer();
}
Comment From: blop
Seems this is getting more urgent: https://www.chromium.org/updates/same-site
See also: https://github.com/eclipse/jetty.project/issues/4247 https://github.com/eclipse-ee4j/servlet-api/issues/175
Comment From: philwebb
@blop Thanks for the links, we'll reopen this one.
Comment From: bclozel
This is properly supported in Spring Framework as of 5.1.10, see spring-projects/spring-framework#23693 and spring-projects/spring-framework#20964 - we'll consider how this should be supported in MVC and WebFlux.
Comment From: lucwillems
i'm current using the default embedded tomcat servlet , spring boot 2.1.8 with NO spring boot session. it seems tomcat can be configured to have a Rfc6265CookieProcessor with sameSite=Strict like this
@Configuration
public class TomcatConfiguration {
@Bean
WebServerFactoryCustomizer<TomcatServletWebServerFactory> cookieProcessorCustomizer() {
return new WebServerFactoryCustomizer<TomcatServletWebServerFactory>() {
@Override
public void customize(TomcatServletWebServerFactory tomcatServletWebServerFactory) {
tomcatServletWebServerFactory.addContextCustomizers(new TomcatContextCustomizer() {
@Override
public void customize(Context context) {
Rfc6265CookieProcessor processor=new Rfc6265CookieProcessor();
processor.setSameSiteCookies("strict");
context.setCookieProcessor(processor);
}
});
}
};
}
}
one remark is that ALL cookies set by this tomcat instance will have sameSite=strict, if that's not what you want, you can extend the cookie processor class and add some custom logic for this.
Comment From: buckett
@lucwillems Thanks for the code snippet, I tried this but Rfc6265CookieProcessor
doesn't output a SameSite
attribute on the cookie if it's set to None
. This means you can't use the class as is for outputting a SameSite=None
attribute to tell Chrome to still send cookies on cross domain requests after Chrome 80 (https://www.chromestatus.com/feature/5088147346030592)
Comment From: rougou
I tried this but
Rfc6265CookieProcessor
doesn't output aSameSite
attribute on the cookie if it's set toNone
.
As you may know, this bug was already fixed at the time of your post, and is now released. https://bz.apache.org/bugzilla/show_bug.cgi?id=63865 https://github.com/apache/tomcat/commit/ec782a03a91cddeab2406d6e16a953a0dcf982a5#diff-1f67ea28105562c05982ddba45cc0527
Comment From: OrangeDog
I feel a headache coming on... It looks like static SameSite configuration isn't going to be sufficient.
Comment From: rougou
Yes, in particular Apple refuses to make a patch for iOS 12, so setting sameSite to None in all cases won't cut it. Ideally DefaultCookieSerializer would allow you to override the sameSite value per request. For a work project, we got around this by making a separate DefaultCookieSerializer instance per sameSite type and switching between them in writeCookieValue().
Comment From: driverpt
FYI, Chrome 80 has now rolled out
Comment From: buckett
Although the SameSite feature is being released more slowly: https://www.chromium.org/updates/same-site
Comment From: samuelstein
An easy way around this problem is to use org.springframework.http.ResponseCookie class. The class has a nice builder with samesite property.
Then you can add the cookie to the response header:
response.addHeader(HttpHeaders.SET_COOKIE, ResponseCookie.from(name, value).build().toString());
Comment From: rstoyanchev
An easy way around this problem is to use org.springframework.http.ResponseCookie class. The class has a nice builder with samesite property. Then you can add the cookie to the response header: response.addHeader(HttpHeaders.SET_COOKIE, ResponseCookie.from(name, value).build().toString());
That's what WebFlux does for Servlet containers and for Netty. For Undertow only it relies on the built-in support.
It is more challenging to do this for Spring MVC where we are not in control of the abstraction. Probably the best route is (for applications) to rely on whatever the underlying server provides since all applications on that server are facing the same issue.
Comment From: mdeinum
I did a little investigation and it appears that at all of the out-of-the-box supported containers (Tomcat, Jetty, Netty and Undertow) each have a custom way of enabling and setting the SameSite attribute. Couldn't this be part of the configuration of the embedded containers, that when set to LAX, STRICT it will be enabled with that value? Or at least with the Servlet containers (as it appears to be workable from a reactive point already).
Comment From: bclozel
Since the initial scope of this issue was about Spring Session, and since we can't obviously solve all the different aspects of this support, I've created different issues for Spring WebFlux #20970 and Servlet-based apps #20971. I'll try and add the relevant information in each issue.
In the meantime, I'm closing this issue in favor of #20961 which is addressing the issue without conflating Spring Session support with future Servlet spec support.
Comment From: bclozel
@mdeinum I've tried to summarize my findings in #20971. As @rstoyanchev pointed out, I'm not sure we're in a position to provide a consistent support with all Servlet containers. Don't hesitate to comment on that issue.