diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/CookiesParser.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/CookiesParser.java index f8bec0a84b..bcd7e5fba7 100644 --- a/core-common/src/main/java/org/glassfish/jersey/message/internal/CookiesParser.java +++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/CookiesParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -120,6 +120,7 @@ private static class MutableNewCookie { boolean secure = false; boolean httpOnly = false; Date expiry = null; + NewCookie.SameSite sameSite = null; public MutableNewCookie(String name, String value) { this.name = name; @@ -127,7 +128,7 @@ public MutableNewCookie(String name, String value) { } public NewCookie getImmutableNewCookie() { - return new NewCookie(name, value, path, domain, version, comment, maxAge, expiry, secure, httpOnly); + return new NewCookie(name, value, path, domain, version, comment, maxAge, expiry, secure, httpOnly, sameSite); } } @@ -163,6 +164,8 @@ public static NewCookie parseNewCookie(String header) { cookie.version = Integer.parseInt(value); } else if (param.startsWith("httponly")) { cookie.httpOnly = true; + } else if (param.startsWith("samesite")) { + cookie.sameSite = NewCookie.SameSite.valueOf(value.toUpperCase()); } else if (param.startsWith("expires")) { try { cookie.expiry = HttpDateFormat.readDate(value + ", " + bites[++i]); diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/NewCookieProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/NewCookieProvider.java index 9c53c742bc..15ab8d06d0 100644 --- a/core-common/src/main/java/org/glassfish/jersey/message/internal/NewCookieProvider.java +++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/NewCookieProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -73,6 +73,10 @@ public String toString(final NewCookie cookie) { if (cookie.isHttpOnly()) { b.append(";HttpOnly"); } + if (cookie.getSameSite() != null) { + b.append(";SameSite="); + b.append(cookie.getSameSite()); + } if (cookie.getExpiry() != null) { b.append(";Expires="); b.append(HttpDateFormat.getPreferredDateFormat().format(cookie.getExpiry())); diff --git a/core-common/src/test/java/org/glassfish/jersey/message/internal/NewCookieProviderTest.java b/core-common/src/test/java/org/glassfish/jersey/message/internal/NewCookieProviderTest.java new file mode 100644 index 0000000000..5a4ba2fc5b --- /dev/null +++ b/core-common/src/test/java/org/glassfish/jersey/message/internal/NewCookieProviderTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.message.internal; + +import jakarta.ws.rs.core.NewCookie; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Date; + +public class NewCookieProviderTest { + + private final NewCookie newCookie = new NewCookie( + "test", + "value", + "/", + "localhost", + 1, + "comment", + 60, + new Date(), + true, + true, + NewCookie.SameSite.STRICT + ); + + @Test + public void SameSiteTest() { + final NewCookieProvider provider = new NewCookieProvider(); + final String newCookieString = provider.toString(newCookie); + Assert.assertTrue(newCookieString.contains("SameSite=STRICT")); + Assert.assertEquals(NewCookie.SameSite.STRICT, provider.fromString(newCookieString).getSameSite()); + } + +} diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/CookiesParserTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/CookiesParserTest.java index 767b6445ac..80b03e0747 100644 --- a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/CookiesParserTest.java +++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/CookiesParserTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -37,14 +37,18 @@ public class CookiesParserTest { @Test public void testCaseInsensitiveNewCookieParams() throws Exception { - _testCaseInsensitiveNewCookieParams("expires", "max-age", "path", "domain", "comment", "version", "secure", "httponly"); - _testCaseInsensitiveNewCookieParams("Expires", "Max-Age", "Path", "Domain", "Comment", "Version", "Secure", "HttpOnly"); - _testCaseInsensitiveNewCookieParams("exPires", "max-aGe", "patH", "doMAin", "Comment", "vErsion", "secuRe", "httPonly"); + _testCaseInsensitiveNewCookieParams("expires", "max-age", "path", "domain", + "comment", "version", "secure", "httponly", "samesite"); + _testCaseInsensitiveNewCookieParams("Expires", "Max-Age", "Path", "Domain", + "Comment", "Version", "Secure", "HttpOnly", "SameSite"); + _testCaseInsensitiveNewCookieParams("exPires", "max-aGe", "patH", "doMAin", + "Comment", "vErsion", "secuRe", "httPonly", "samEsite"); } private void _testCaseInsensitiveNewCookieParams(final String expires, final String maxAge, final String path, final String domain, final String comment, final String version, - final String secure, final String httpOnly) throws Exception { + final String secure, final String httpOnly, final String sameSite) + throws Exception { final String header = "foo=bar;" + expires + "=Tue, 15 Jan 2013 21:47:38 GMT;" @@ -54,7 +58,8 @@ private void _testCaseInsensitiveNewCookieParams(final String expires, final Str + comment + "=Testing;" + version + "=1;" + secure + ";" - + httpOnly; + + httpOnly + ";" + + sameSite + "=STRICT"; final NewCookie cookie = CookiesParser.parseNewCookie(header); @@ -69,5 +74,6 @@ private void _testCaseInsensitiveNewCookieParams(final String expires, final Str assertThat(cookie.getVersion(), equalTo(1)); assertThat(cookie.isSecure(), is(true)); assertThat(cookie.isHttpOnly(), is(true)); + assertThat(cookie.getSameSite(), equalTo(NewCookie.SameSite.STRICT)); } } diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CookieImplTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CookieImplTest.java index 1d8c7de363..a5f04a749c 100644 --- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CookieImplTest.java +++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CookieImplTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -187,6 +187,12 @@ public void testNewCookieToString() { cookie = new NewCookie("fred", "flintstone", null, null, "a modern stonage family", 60, false); expResult = "fred=flintstone;Version=1;Comment=\"a modern stonage family\";Max-Age=60"; assertEquals(expResult, cookie.toString()); + + cookie = new NewCookie("fred", "flintstone", null, null, 1, + "a modern stonage family", 60, null, false, false, + NewCookie.SameSite.STRICT); + expResult = "fred=flintstone;Version=1;Comment=\"a modern stonage family\";Max-Age=60;SameSite=STRICT"; + assertEquals(expResult, cookie.toString()); } @Test @@ -209,6 +215,16 @@ public void testNewCookieValueOf() { assertEquals(1, cookie.getVersion()); assertEquals(60, cookie.getMaxAge()); assertTrue(cookie.isSecure()); + + cookie = NewCookie.valueOf( + "fred=flintstone;Version=1;Comment=\"a modern stonage family\";Max-Age=60;Secure;SameSite=NONE"); + assertEquals("fred", cookie.getName()); + assertEquals("flintstone", cookie.getValue()); + assertEquals("a modern stonage family", cookie.getComment()); + assertEquals(1, cookie.getVersion()); + assertEquals(60, cookie.getMaxAge()); + assertTrue(cookie.isSecure()); + assertEquals(NewCookie.SameSite.NONE, cookie.getSameSite()); } }