Repository: vert-x3/vertx-web
Issue: SessionHandler doesn't set SameSite cookie attribute when destroying the session and expiring the session cookie 

### Questions

When the session cookie needs to be removed on session logout, the SameSite attribute is not set. 

### Version

3.9.2

### Context

If SameSite.None is set on the cookie while setting it for the duration of the session, It should also be present when the user sends a logout and the expiration of the cookie is set.
The logout can be called from different locations where the SameSite.None is needed for it to function.
Now because it's not set, the cookie remains, and the session is still available.

### Do you have a reproducer?

It's on line 196 in io.vertx.ext.web.handler.impl.SessionHandlerImpl. The cookie is removed when the session gets destroyed. But the additional attributes are not there.

I duplicated the SessionHandlerImpl class and added the following code to get it to work. I can add a pull request, to add the cookie handling in the SessionHandlerImpl itself. 

```
...
        } else {
            // invalidate the cookie as the session has been destroyed
            context.removeCookie(sessionCookieName);

/* added from here*/
            Cookie cookie = context.getCookie(sessionCookieName);
            if (cookie != null) {
                cookie.setPath(sessionCookiePath);
                cookie.setSecure(sessionCookieSecure);
                cookie.setHttpOnly(sessionCookieHttpOnly);
                cookie.setSameSite(cookieSameSite);
                context.addCookie(cookie);
            }
/* until here*/

            // if the session was regenerated in the request
            // the old id must also be removed
            if (session.isRegenerated()) {
...
```


Changed files:
vertx-web/src/test/java/io/vertx/ext/web/handler/SessionHandlerTestBase.java, vertx-web/src/main/java/io/vertx/ext/web/handler/impl/SessionHandlerImpl.java

diff --git a/vertx-web/src/main/java/io/vertx/ext/web/handler/impl/SessionHandlerImpl.java b/vertx-web/src/main/java/io/vertx/ext/web/handler/impl/SessionHandlerImpl.java
index 367e27de1..c9934625c 100644
--- a/vertx-web/src/main/java/io/vertx/ext/web/handler/impl/SessionHandlerImpl.java
+++ b/vertx-web/src/main/java/io/vertx/ext/web/handler/impl/SessionHandlerImpl.java
@@ -146,14 +146,16 @@ public class SessionHandlerImpl implements SessionHandler {
    *
    * @param cookie the cookie to set
    */
-  private void setCookieProperties(Cookie cookie) {
+  private void setCookieProperties(Cookie cookie, boolean expired) {
     cookie.setPath(sessionCookiePath);
     cookie.setSecure(sessionCookieSecure);
     cookie.setHttpOnly(sessionCookieHttpOnly);
     cookie.setSameSite(cookieSameSite);
-    // set max age if user requested it - else it's a session cookie
-    if (cookieMaxAge >= 0) {
-      cookie.setMaxAge(cookieMaxAge);
+    if (!expired) {
+      // set max age if user requested it - else it's a session cookie
+      if (cookieMaxAge >= 0) {
+        cookie.setMaxAge(cookieMaxAge);
+      }
     }
   }
 
@@ -190,7 +192,7 @@ public class SessionHandlerImpl implements SessionHandler {
             // restore defaults
             session.setAccessed();
             cookie.setValue(session.value());
-            setCookieProperties(cookie);
+            setCookieProperties(cookie, false);
           }
 
           // we must invalidate the old id
@@ -234,7 +236,10 @@ public class SessionHandlerImpl implements SessionHandler {
     } else {
       if (!cookieless) {
         // invalidate the cookie as the session has been destroyed
-        context.removeCookie(sessionCookieName);
+        final Cookie expiredCookie = context.removeCookie(sessionCookieName);
+        if (expiredCookie != null) {
+          setCookieProperties(expiredCookie, true);
+        }
       }
       // if the session was regenerated in the request
       // the old id must also be removed
@@ -450,7 +455,7 @@ public class SessionHandlerImpl implements SessionHandler {
       return cookie;
     }
     cookie = Cookie.cookie(sessionCookieName, session.value());
-    setCookieProperties(cookie);
+    setCookieProperties(cookie, false);
     context.addCookie(cookie);
     return cookie;
   }
diff --git a/vertx-web/src/test/java/io/vertx/ext/web/handler/SessionHandlerTestBase.java b/vertx-web/src/test/java/io/vertx/ext/web/handler/SessionHandlerTestBase.java
index 12bd307b3..e11505e8f 100644
--- a/vertx-web/src/test/java/io/vertx/ext/web/handler/SessionHandlerTestBase.java
+++ b/vertx-web/src/test/java/io/vertx/ext/web/handler/SessionHandlerTestBase.java
@@ -16,6 +16,7 @@
 
 package io.vertx.ext.web.handler;
 
+import io.vertx.core.http.CookieSameSite;
 import io.vertx.core.http.HttpMethod;
 import io.vertx.ext.web.Session;
 import io.vertx.ext.web.WebTestBase;
@@ -381,6 +382,7 @@ public abstract class SessionHandlerTestBase extends WebTestBase {
 		testRequest(HttpMethod.GET, "/0", req -> {
 		}, resp -> {
 			String setCookie = resp.headers().get("set-cookie");
+			System.out.println(setCookie);
 			sessionID.set(setCookie);
 		}, 200, "OK", null);
 		CountDownLatch responseReceived = new CountDownLatch(1);
@@ -393,6 +395,38 @@ public abstract class SessionHandlerTestBase extends WebTestBase {
 		return MILLISECONDS.convert(System.nanoTime() - now, NANOSECONDS);
 	}
 
+  @Test
+  public void testInvalidation() throws Exception {
+    router.route().handler(SessionHandler.create(store).setCookieSameSite(CookieSameSite.STRICT));
+    AtomicReference<Session> rid = new AtomicReference<>();
+
+    router.get("/0").handler(rc -> {
+      rid.set(rc.session());
+      rc.session().put("foo", "foo_value");
+      rc.response().end();
+    });
+    router.get("/1").handler(rc -> {
+      rid.set(rc.session());
+      assertEquals("foo_value", rc.session().get("foo"));
+      rc.session().destroy();
+      rc.response().end();
+    });
+
+    AtomicReference<String> sessionID = new AtomicReference<>();
+    testRequest(HttpMethod.GET, "/0", req -> {
+    }, resp -> {
+      String setCookie = resp.headers().get("set-cookie");
+      sessionID.set(setCookie);
+    }, 200, "OK", null);
+    CountDownLatch responseReceived = new CountDownLatch(1);
+    testRequest(HttpMethod.GET, "/1", req -> req.putHeader("cookie", sessionID.get()), resp -> {
+      // ensure that expired cookies still contain the the configured properties
+      assertTrue(resp.headers().get("set-cookie").contains("SameSite=Strict"));
+      responseReceived.countDown();
+    }, 200, "OK", null);
+    awaitLatch(responseReceived);
+  }
+
 	@Test
 	public void testSessionFixation() throws Exception {