Tomcat and Jetty SameSite Workarounds


Summary


Newer versions of Tomcat (8.5.42 and 9.0.21 onward) and Jetty (9.4.21 onward) offer mechanisms for setting the same-site cookie attribute on cookies. Neither of which are standardised, and neither are compatible between containers. It looks like the earliest point from which the Servlet Specification will contain support for same-site is v5.1. Support for servlet spec v5.1 is likely (but not guaranteed) to arrive in Jetty version 11 and Tomcat 10.X. In my opinion most implementations of Java servlets use version 3.1 of the spec. and so a future using v5.1 seems a long way off. 

Jetty's 'workaround' relies on encoding the same-site value into a cookie's comment attribute which is later extracted and added to the Set-Cookie header by its own Response object - v9.4.23 onward allow this to be set on the session cookie also. Unless container 'sniffing' was used, this approach would silently fail inside other containers. 

Tomcat's 'workaround' to add SameSite is potentially less configurable by default, as it globally applies to all cookies a single configured same-site value (including the session cookie). This could be extended using a custom CookieProcessor, but as there seems no way to access the HttpRequest, it still may not be suitable for conditionally applying values by user-agent etc.

Tomcat and Jetty Servlet Specification Support

ContainerVersionServlet Spec
Jetty9.33.1
Jetty9.43.1
Jetty104.0.2
Jetty115.0 in jakarta namespace, release soon after 10
Tomcat8.5.x3.1
Tomcat9.0.x4.0
Tomcat10.0.x5.0 in jakarta namespace

Servlet Specification SameSite Standardisation

4.0, 4.0.1 or 4.0.2

No changes to the cookie API to allow setting SameSite.

5.0

It is hard to find meaningful documentation on the (in development) Jakarta servlet spec version 5.0 e.g. Jakarta Servlet 5.0 (Under Development) | The Eclipse Foundation, but it does seem to exist in their GitHub code repository: servlet-api/servlet-spec-body.adoc at master · eclipse-ee4j/servlet-api · GitHub, alongside the API code. It is possible the only significant change between v4.0 and v5.0 is to the package namespace i.e. from javax.* to jakarta.*.

There is no mention of SameSite in the current version of the v5 specification. This issue suggests they are targeting v5.1 of the specification i.e. SameSite Cookie Support · Issue #175 · eclipse-ee4j/servlet-api · GitHub, and #175 Add support for SameSite cookies by aldaris · Pull Request #271 · eclipse-ee4j/servlet-api · GitHub. See also their milestone 5.1 · GitHub.

The latest merge request to add this to the specification is #175 Add support for SameSite cookies by aldaris · Pull Request #271 · eclipse-ee4j/servlet-api · GitHub

Servlet Containers

Jetty

9.4.21

Jetty added (unstandardised) support for setting same-site to cookies in 9.4.21.v20190926 (Allow RFC6265 Cookies to include optional SameSite attribute. · Issue #3040 · eclipse/jetty.project · GitHub). A same-site value is encoded into the cookie’s comment attribute, which is later extracted by the Jetty response object and added to the Set-Cookie header. For example:

Cookie cookieHttp = new Cookie("cookiename","value");
cookieHttp.setComment(HttpCookie.SAME_SITE_NONE_COMMENT);
response.addCookie(cookieHttp);

You could add this directly to the Jetty Response as a Jetty HttpCookie object with explicitly set same-site value - but that requires casting the HttpServletResponse to the Jetty Response type

As this is left to the developer, it could be added conditionally based on user-agent, however the approach only applies to Jetty.

Issues:

  • There is no way to add this to the session cookie i.e. JSESSIOND.
  • There is no way to set a default value if a value is not added to a cookie's comments.
  • Unstandardized Jetty specific approach.

9.4.23

In addition to the above, Jetty version 9.4.23 allows setting the session cookie same-site attribute in the session cookie config (Issue #4247 SameSite Session Cookie by gregw · Pull Request #4271 · eclipse/jetty.project · GitHub). For example, in the web.xml:

  <session-config>
    <cookie-config>
      <comment>__SAME_SITE_NONE__</comment>
    </cookie-config>
  </session-config>

This does set the JESSIONID to None when testing the IdP using Jetty 9.4.26. This does indeed break safari in 10.14 (None->Strict). 


Issues:

  • There is no way to set a default value if a value is not added to the comments.
  • There does not seem to be a way to conditionally add (e.g. by user-agent) this to the session cookie.
  • Unstandardized Jetty specific approach.

9.4.27

Jetty 9.4.27 added support for setting a global, default, same-site value from the servlet context (servlet context attribute) if not already encoded in the cookie's comment (as above) (Issue #4247 use context default for samesite cookie attribute by janbartel · Pull Request #4512 · eclipse/jetty.project · GitHub)

Issues that remain:

  • There does not seem to be a way to do this conditionally by user-agent for the session cookie.
  • Unstandardised Jetty specific approach.

Safari Issue

For application defined/set cookies, the developer is responsible for adding the same-site value to the cookie’s comments, which would allow setting IdP cookies to None alongside user-agent testing. However, this would silently fail if another container implementation was used - the same-site value would instead end up in the cookie comment and not processed by the browser.

The session cookie behaviour is not controllable to allow conditional setting based on the user-agent (or similar). The comment is simply added blindly to the session cookie in the SessionHandler#getSessionCookie(), and later extracted by Jetty’s Response object.

Tomcat

Of relevance here, you can define your own cookie processor in tomcat, org.apache.tomcat.util.http.Rfc6265CookieProcessor (Apache Tomcat 8 Configuration Reference (8.5.51) - The Cookie Processor Component).

8.5.42

Tomcat 8.5.42 introduced a global same-site cookie setting in the default Rfc6265CookieProcessor.

(Add: Add support for same-site cookie attribute. Patch provided by John Kelly. (markt))

The CookieProcessor is attached to the ServletContext and is therefore specific to an individual web application. The samesite value applies unconditionally to all cookies, even the JSESSIONID. For example, this can be configured in the context.xml file as:

<Context>
   <CookieProcessor sameSiteCookies="strict" />
</Context>

Issues:

  • The default implementation is not conditional on the user-agent.
  • The default implementation does not allow individual cookies to have different same-site values
    • You would need to implement your own CookieProcessor to manage this.
  • Unstandardised Tomcat specific approach.


8.5.48

Tomcat 8.5.48 fixed a bug in the previous version where a SameSite ‘None’ configuration was being ignored, adding a same-site UNSET option 63865 – Cookie Attribute SameSite=None is default to unset in Chrome browser. For example, prior to 8.5.48:

if (!sameSiteCookiesValue.equals(SameSiteCookies.NONE)) {
            header.append("; SameSite=");
            header.append(sameSiteCookiesValue.getValue());
}

In 8.5.48:

 if (!sameSiteCookiesValue.equals(SameSiteCookies.UNSET)) {
            header.append("; SameSite=");
            header.append(sameSiteCookiesValue.getValue());
}


Issues:


  • The default implementation is not conditional on the user-agent.
  • The default implementation does not allow individual cookies to have different same-site values
    • You would need to implement your own CookieProcessor to manage this.
  • Unstandardized Tomcat specific approach.

9.0.21, 9.0.28, and onward

Tomcat 9.0.21 onward contains the same samesite feature as was backported to 8.5.42.

Tomcat 9.0.28 onward contains the same fix to SameSite=None not being set as 8.5.48.

Safari Issue

The CookieProcessor does not have access to the HttpRequest, I can not see a way for it to test the user-agent etc. and hence conditionally set same-site. In theory it ‘could’ be used for the 2-cookie-solution, however that would mean using a single Set-Cookie header with a comma seperated list of cookies - which is deprecated in 6265 and ignored by most browsers.