remix icon indicating copy to clipboard operation
remix copied to clipboard

`destroySession` doesn't delete cookie if max-age is set

Open AlexErrant opened this issue 2 years ago • 0 comments

What version of Remix are you using?

v1.11.0

Steps to Reproduce

  1. Create a cookie session storage with maxAge set
  storage = createCookieSessionStorage({
    cookie: {
      name: "__Host-session",
      secure: true,
      sameSite: "lax",
      path: "/",
      maxAge: 60 * 60 * 24 * 30, // 30 days
      httpOnly: true,
    },
  })
  1. Destroy it
  const session = await storage.getSession(request.headers.get("Cookie"))
  const headers = new Headers()
  headers.append("Set-Cookie", await storage.destroySession(session))

Expected Behavior

I expected the cookie to be deleted.

Actual Behavior

Instead, I get a set-cookie response header that looks like

__Host-session=; Max-Age=2592000; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Secure; SameSite=Lax

Remix blanks out the session, which is great, and causes logouts to work as expected.

Remix also sets the Expires set to the epoch, which is a spec-compliant way of deleting the cookie:

servers can delete cookies by sending the user agent a new cookie with an Expires attribute with a value in the past.

However, the spec also states:

If a cookie has both the Max-Age and the Expires attribute, the Max-Age attribute has precedence and controls the expiration date of the cookie.

My interpretation is that if Max-Age is set, setting the Expires to the epoch doesn't change the cookie's expiration. This is reflected in Chrome, where the above response header does not result in the cookie being deleted.

Code_YLatP5tpkB

May I suggest implementing this code as

        return cookie.serialize("", {
          ...options,
          maxAge: undefined,
          expires: new Date(0)
        });

AlexErrant avatar Jan 19 '23 18:01 AlexErrant