Skip to content

SameSite cookie attribute missing when using WebFlux #23693

Closed
@essh

Description

@essh

As of Spring Framework 5.1 the "What’s New” wiki documentation states the following for Spring WebFlux (https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-5.x#spring-webflux-1):

"Session cookies now have SameSite=Lax to protect against CSRF attacks”

In practice this is not true when using any of the framework supplied HttpHandler adapters and no SameSite attribute is added to session cookies. This is dangerous as a user may read this note and assume that the SameSite attribute will be set to a value that will prevent CSRF on all modern browsers (https://caniuse.com/#feat=same-site-cookie-attribute) when using Spring WebFlux >= 5.1.

You can verify that the SameSite attribute is not being added to session cookies on WebFlux by default by creating a new Spring Boot WebFlux project on the Spring Initializr, creating a controller that sets an attribute on the session, and then making a HTTP request to this controller method and inspecting the returned session cookie.

The issue seems to be that internally the framework uses a ResponseCookie that does set the SameSite attribute to “Lax" by default. However, all of the ServerHttpResponse adapters for the various servers do not copy the SameSite attribute into the resulting cookie when calling their applyCookies() method:

ReactorServerHttpResponse -

protected void applyCookies() {
for (String name : getCookies().keySet()) {
for (ResponseCookie httpCookie : getCookies().get(name)) {
Cookie cookie = new DefaultCookie(name, httpCookie.getValue());
if (!httpCookie.getMaxAge().isNegative()) {
cookie.setMaxAge(httpCookie.getMaxAge().getSeconds());
}
if (httpCookie.getDomain() != null) {
cookie.setDomain(httpCookie.getDomain());
}
if (httpCookie.getPath() != null) {
cookie.setPath(httpCookie.getPath());
}
cookie.setSecure(httpCookie.isSecure());
cookie.setHttpOnly(httpCookie.isHttpOnly());
this.response.addCookie(cookie);
}
}
}

UndertowServerHttpResponse -

protected void applyCookies() {
for (String name : getCookies().keySet()) {
for (ResponseCookie httpCookie : getCookies().get(name)) {
Cookie cookie = new CookieImpl(name, httpCookie.getValue());
if (!httpCookie.getMaxAge().isNegative()) {
cookie.setMaxAge((int) httpCookie.getMaxAge().getSeconds());
}
if (httpCookie.getDomain() != null) {
cookie.setDomain(httpCookie.getDomain());
}
if (httpCookie.getPath() != null) {
cookie.setPath(httpCookie.getPath());
}
cookie.setSecure(httpCookie.isSecure());
cookie.setHttpOnly(httpCookie.isHttpOnly());
this.exchange.getResponseCookies().putIfAbsent(name, cookie);
}
}
}

ServletServerHttpResponse -

protected void applyCookies() {
for (String name : getCookies().keySet()) {
for (ResponseCookie httpCookie : getCookies().get(name)) {
Cookie cookie = new Cookie(name, httpCookie.getValue());
if (!httpCookie.getMaxAge().isNegative()) {
cookie.setMaxAge((int) httpCookie.getMaxAge().getSeconds());
}
if (httpCookie.getDomain() != null) {
cookie.setDomain(httpCookie.getDomain());
}
if (httpCookie.getPath() != null) {
cookie.setPath(httpCookie.getPath());
}
cookie.setSecure(httpCookie.isSecure());
cookie.setHttpOnly(httpCookie.isHttpOnly());
this.response.addCookie(cookie);
}
}
}

This may be somewhat problematic to fix using the existing logic that delegates to the server Cookie implementation as only Undertow currently has a method to set the SameSite attribute.

Also related to this issue is that in the near future Chrome will default cookies that do not have a SameSite attribute to “Lax” (https://www.chromestatus.com/feature/5088147346030592) which may break some applications if they have no ability to change the value of the SameSite attribute.

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)type: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions