diff --git a/src/main/java/io/vertx/core/http/Cookie.java b/src/main/java/io/vertx/core/http/Cookie.java index f0154070c..5603fbb3c 100644 --- a/src/main/java/io/vertx/core/http/Cookie.java +++ b/src/main/java/io/vertx/core/http/Cookie.java @@ -121,12 +121,11 @@ public interface Cookie { /** * Sets the same site of this cookie. * - * @param policy The policy should be one of {@code Lax}, {@code Strict} or {@code None} + * @param policy The policy should be one of {@link CookieSameSite}. * @return a reference to this, so the API can be used fluently */ @Fluent - Cookie setSameSite(String policy); - + Cookie setSameSite(CookieSameSite policy); /** * Encode the cookie to a string. This is what is used in the Set-Cookie header diff --git a/src/main/java/io/vertx/core/http/CookieSameSite.java b/src/main/java/io/vertx/core/http/CookieSameSite.java new file mode 100644 index 000000000..8aeb1dd04 --- /dev/null +++ b/src/main/java/io/vertx/core/http/CookieSameSite.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2011-2019 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 + */ +package io.vertx.core.http; + +import io.vertx.codegen.annotations.VertxGen; + +/** + * Represents the Cookie SameSite policy to be used. For more info https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_cookies. + * + * @author Paulo Lopes + */ +@VertxGen +public enum CookieSameSite { + + /** + * The browser will send cookies with both cross-site requests and same-site requests. + */ + NONE("None"), + + /** + * The browser will only send cookies for same-site requests (requests originating from the site that set the cookie). + * If the request originated from a different URL than the URL of the current location, none of the cookies tagged + * with the Strict attribute will be included. + */ + STRICT("Strict"), + + /** + * Same-site cookies are withheld on cross-site subrequests, such as calls to load images or frames, but will be sent + * when a user navigates to the URL from an external site; for example, by following a link. + */ + LAX("Lax"); + + /** + * Just use a human friendly label instead of the capitalized name. + */ + private final String label; + + CookieSameSite(String label) { + this.label = label; + } + + @Override + public String toString() { + return label; + } +} diff --git a/src/main/java/io/vertx/core/http/impl/CookieImpl.java b/src/main/java/io/vertx/core/http/impl/CookieImpl.java index bc6cae934..649c4cb6d 100644 --- a/src/main/java/io/vertx/core/http/impl/CookieImpl.java +++ b/src/main/java/io/vertx/core/http/impl/CookieImpl.java @@ -15,6 +15,7 @@ import io.netty.handler.codec.http.cookie.DefaultCookie; import io.netty.handler.codec.http.cookie.ServerCookieDecoder; import io.netty.handler.codec.http.cookie.ServerCookieEncoder; import io.vertx.core.http.Cookie; +import io.vertx.core.http.CookieSameSite; import java.util.HashMap; import java.util.Map; @@ -64,7 +65,7 @@ public class CookieImpl implements ServerCookie { private boolean changed; private boolean fromUserAgent; // extension features - private String sameSite; + private CookieSameSite sameSite; public CookieImpl(String name, String value) { this.nettyCookie = new DefaultCookie(name, value); @@ -139,30 +140,7 @@ public class CookieImpl implements ServerCookie { } @Override - public Cookie setSameSite(final String sameSite) { - if (sameSite != null) { - // validate - int length = sameSite.length(); - switch (length) { - case 3: - if (!sameSite.equalsIgnoreCase("LAX")) { - throw new IllegalArgumentException("sameSite contains an invalid value: " + sameSite); - } - break; - case 4: - if (!sameSite.equalsIgnoreCase("NONE")) { - throw new IllegalArgumentException("sameSite contains an invalid value: " + sameSite); - } - break; - case 6: - if (!sameSite.equalsIgnoreCase("STRICT")) { - throw new IllegalArgumentException("sameSite contains an invalid value: " + sameSite); - } - break; - default: - throw new IllegalArgumentException("sameSite contains an invalid value: " + sameSite); - } - } + public Cookie setSameSite(final CookieSameSite sameSite) { this.sameSite = sameSite; this.changed = true; return this; @@ -171,7 +149,7 @@ public class CookieImpl implements ServerCookie { @Override public String encode() { if (sameSite != null) { - return ServerCookieEncoder.STRICT.encode(nettyCookie) + "; SameSite=" + sameSite; + return ServerCookieEncoder.STRICT.encode(nettyCookie) + "; SameSite=" + sameSite.toString(); } else { return ServerCookieEncoder.STRICT.encode(nettyCookie); } diff --git a/src/test/java/io/vertx/core/http/HttpTest.java b/src/test/java/io/vertx/core/http/HttpTest.java index 061247208..d3ae7ee5b 100644 --- a/src/test/java/io/vertx/core/http/HttpTest.java +++ b/src/test/java/io/vertx/core/http/HttpTest.java @@ -5405,15 +5405,15 @@ public abstract class HttpTest extends HttpTestBase { @Test public void testCookieSameSiteFieldEncoding() throws Exception { - Cookie cookie = Cookie.cookie("foo", "bar").setSameSite("lax"); + Cookie cookie = Cookie.cookie("foo", "bar").setSameSite(CookieSameSite.LAX); assertEquals("foo", cookie.getName()); assertEquals("bar", cookie.getValue()); - assertEquals("foo=bar; SameSite=lax", cookie.encode()); + assertEquals("foo=bar; SameSite=Lax", cookie.encode()); cookie.setSecure(true); - assertEquals("foo=bar; Secure; SameSite=lax", cookie.encode()); + assertEquals("foo=bar; Secure; SameSite=Lax", cookie.encode()); cookie.setHttpOnly(true); - assertEquals("foo=bar; Secure; HTTPOnly; SameSite=lax", cookie.encode()); + assertEquals("foo=bar; Secure; HTTPOnly; SameSite=Lax", cookie.encode()); } @Test @@ -5421,36 +5421,17 @@ public abstract class HttpTest extends HttpTestBase { Cookie cookie = Cookie.cookie("foo", "bar"); try { - cookie.setSameSite("Lax"); + cookie.setSameSite(CookieSameSite.LAX); // OK - cookie.setSameSite("Strict"); + cookie.setSameSite(CookieSameSite.STRICT); // OK - cookie.setSameSite("NoNe"); + cookie.setSameSite(CookieSameSite.NONE); // OK cookie.setSameSite(null); // OK } catch (RuntimeException e) { fail(); } - - try { - cookie.setSameSite("XYZ"); - fail(); - } catch (RuntimeException e) { - // OK - } - try { - cookie.setSameSite("DURP"); - fail(); - } catch (RuntimeException e) { - // OK - } - try { - cookie.setSameSite("some random stuff"); - fail(); - } catch (RuntimeException e) { - // OK - } } @Test