Skip to content

Support setting both partitioned and unpartitioned cookies of the same domain/path/name #58774

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
JonathanGawrych opened this issue Nov 5, 2024 · 2 comments

Comments

@JonathanGawrych
Copy link

Description

In ResponseHeaderBag's setCookie() function:

$this->cookies[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie;
cookies are set based on their domain, path, and name. However there's one more category that partitions cookies, ironically named partitioned. You can set both partitioned and unpartitioned cookies at the same time. Unfortunately the ResponseHeaderBag doesn't allow this.

What's the use case you may ask? We have a site that can either be opened in an iframe or at a top level window in a new tab. We set our auth cookie to partitioned inside the iframe and not partitioned in a new tab. This is done in a classroom setting where multiple users often use a single machine. If they only use iframes or only use new tabs, then there's no problem. However, once you mix the two, you can have a case where the new tab cookie leaks into the iframe. Both cookies are then sent with requests, causing the user inside of the iframe to potentially logged in as the last user who had a new tab logged in instead.

To counteract this, we attempt to log out (delete the previous cookies) when a user logs in. However, we need to delete the unpartitioned cookie, and set the partitioned one in the same response. Setting the partitioned cookie overwrites deleting the unpartitioned cookie. The code example below shows a minimal reproduction. Right now our workaround is to use a raw header() statement, which is less than ideal. Note that we are also using Laravel, but before we can make any PR there, we first need to make one here.

Thanks for your work!

Example

<?php
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Cookie;

$response = new Response();
// Log out the old user outside the iframe so the cookie doesn't leak inside the iframe
$response->headers->setCookie(new Cookie('auth', null, sameSite: Cookie::SAMESITE_NONE, partitioned: false));

// Log in the new user by setting their cookie.
$response->headers->setCookie(new Cookie('auth', 'new_token', time() + 7200, sameSite: Cookie::SAMESITE_NONE, partitioned: true));

echo implode('\n', array_map(fn ($cookie) => (string) $cookie, $response->headers->getCookies()));

// expected:
// auth=deleted; expires=Mon, 06 Nov 2023 21:31:24 GMT; Max-Age=0; path=/; httponly; samesite=none
// auth=new_token; expires=Tue, 05 Nov 2024 23:31:57 GMT; Max-Age=7198; path=/; httponly; samesite=none; partitioned

// actual:
// auth=new_token; expires=Tue, 05 Nov 2024 23:31:57 GMT; Max-Age=7198; path=/; httponly; samesite=none; partitioned
@carsonbot
Copy link

Thank you for this issue.
There has not been a lot of activity here for a while. Has this been resolved?

@carsonbot
Copy link

Friendly reminder that this issue exists. If I don't hear anything I'll close this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants