10

I'm unable to set SameSite cookie value to None.

Following is how i'm generating ResponseCookie object.

ResponseCookie cookie = ResponseCookie.from("Hb", cookieUserId)
            .maxAge(!isEmpty(cookieUserId) ? MAX_COOKIE_DURATION : 0)
            .domain("test.com")
            .sameSite("None")
            .secure(true)
            .path("/")
            .build();
 response.addCookie(cookie)

Curl request to endpoint

curl -X POST "localhost:8080/v1/user/v" --data "{}" -v -H 'Content-Type: application/json'

Response:

< set-cookie: Hb=00b7be31-fc6d-4891-a07c-46b5ef2b423c; Max-Age=7776000; Expires=Fri, 8 Nov 2019 17:23:52 GMT; Path=/; Domain=test.com; Secure

As you can see SameSite attribute is missing from the cookie.

Spring Boot (version: 2.1.3.RELEASE) dependency

        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
Ahmad.Masood
  • 1,289
  • 3
  • 21
  • 40
  • Here is a solution for Undertow 2.1.0 Final and later [https://stackoverflow.com/a/65993991/2284150](https://stackoverflow.com/a/65993991/2284150) – Mihail Feb 01 '21 at 14:04
  • Worked solution for me. Hope this will be a help to someone https://stackoverflow.com/a/64558083/4423695 – ThilankaD Feb 06 '21 at 12:20

4 Answers4

9

I think the issue is that the underlying javax.servlet.http.Cookie does not support the SameSite attribute, let alone the new None value.

Instead you can set this directly as a header, assuming your response is an instance of javax.servlet.http.HttpServletResponse:

ResponseCookie cookie = ResponseCookie.from("Hb", cookieUserId)
            .maxAge(!isEmpty(cookieUserId) ? MAX_COOKIE_DURATION : 0)
            .domain("test.com")
            .sameSite("None")
            .secure(true)
            .path("/")
            .build();
 response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
rowan_m
  • 2,893
  • 15
  • 18
2

Here is a solution using your own CookieSerializer bean. You can simply add this to your BootApplication Class:

@Bean
public CookieSerializer cookieSerializer() {
    DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
    cookieSerializer.setSameSite("None");
    return cookieSerializer;
}

However this will override the default spring session attributes like the session same server.servlet.session.cookie.name and maxAge server.servlet.session.cookie.max-age. So a more complete solution looks like this:

...
@Autowired
private CookieConfiguration cookieConfiguration;

@Bean
public CookieSerializer cookieSerializer() {
    DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
    cookieSerializer.setSameSite("None");
    cookieSerializer.setCookieName(cookieConfiguration.getName());
    cookieSerializer.setDomainName(cookieConfiguration.getDomain());
    cookieSerializer.setCookiePath(cookieConfiguration.getPath());
    cookieSerializer.setUseHttpOnlyCookie(cookieConfiguration.isHttpOnly());
    cookieSerializer.setUseSecureCookie(cookieConfiguration.isSecure());
    cookieSerializer.setCookieMaxAge((Long.valueOf(cookieConfiguration.getMaxAge().toSeconds())).intValue());
    // TODO check if rememberMeServices need additional configuration here

    return cookieSerializer;
}

And the Configuration Class.

@ConfigurationProperties(prefix = "server.servlet.session.cookie")
@Configuration("cookieProperties")
@Getter
@Setter
public class CookieConfiguration {

    private String comment;
    private String domain;
    private boolean httpOnly;
    private Duration maxAge;
    private String name;
    private String path;
    private boolean secure;

}

I'm not sure if there is a better solution to apply the configuration properties and only override the samesite attribute. I can imagine in a future spring boot version this option/property will be included. Also as you see in the TODO code comment I did not test this solution with active remember-me services. The solution was tested in spring boot version 2.1.6.RELEASE and inspire from the code found in org/springframework/boot/autoconfigure/session/SessionAutoConfiguration.class.

LukeSolar
  • 3,795
  • 4
  • 32
  • 39
2

You can configure SameSite via TomcatContextCustomizer:

@Configuration
public class MvcConfiguration implements WebMvcConfigurer {

  @Bean
  public TomcatContextCustomizer sameSiteCookiesConfig() {
    return context -> {
        final Rfc6265CookieProcessor cookieProcessor = new Rfc6265CookieProcessor();
        cookieProcessor.setSameSiteCookies(SameSiteCookies.NONE.getValue());
        context.setCookieProcessor(cookieProcessor);
    };
  }

Cookies for cross-site usage must specify SameSite=None; Secure to enable inclusion in third party context (https://web.dev/samesite-cookie-recipes/).

bmilczarek
  • 91
  • 3
  • 7
-1

LukeSolar's answer was correct.The DefaultCookieSerializer is in the spring-session jar.So you need to add spring-session dependencies. You can refer to the official documentation https://spring.io/projects/spring-session