Cookies over HTTP
Handle cross-site and partitioned cookies
Distinguish SameSite rules from partitioned cookies and avoid depending on unrestricted third-party state.
When your content is embedded in someone else’s page, a cookie has two contexts. Who set it, and which top-level site the browser is showing. Two different mechanisms deal with that, and people mix them up.
SameSite decides delivery
SameSite answers one question: should the browser attach this cookie to a cross-site request, where the top-level site differs from the cookie’s site?
Strict: never. Even a link from another site to yours arrives without the cookieLax: only on top-level navigations with safe methods likeGET. Not on embedded requests, not on cross-sitePOSTNone: always. The browser requiresSecurealongside it
For the field-notes session, Lax is right. Users click a link from an email and arrive logged in, but a hidden form on another site can’t post as them.
Now suppose our app ships an embeddable widget, an iframe that shows a shared note on other people’s sites. Its requests are cross-site by definition, so it needs SameSite=None.
Partitioned decides the storage key
SameSite=None used to mean one cookie jar for the widget, shared across every site that embeds it. That’s the classic third-party cookie, and browsers restrict it because it’s also how cross-site tracking works.
The Partitioned attribute changes the storage key. The cookie is stored under “widget origin, inside top-level site X”. Embedded on hikingclub.org you get one jar. Embedded on trailmaps.net you get another. Same browser, same widget server, two separate cookies.
Set-Cookie: __Host-widget=compact; Path=/; Secure; SameSite=None; Partitioned
This is a fair trade. The widget keeps per-site state, like a collapsed panel or a preferred language. It can’t recognize the same person across sites.
Partitioning doesn’t make the cookie first-party, and it doesn’t let the widget read the host site’s cookies. It only splits the widget’s own jar.
Design for zero cross-site cookies
Browser policies here keep changing. Safari and Firefox block unpartitioned third-party cookies by default. Chrome’s rules keep shifting.
My advice is to design embeds to work without cross-site cookies at all, and treat partitioned state as a bonus. Pass what the widget needs in the URL or through postMessage from the host page. Then test with third-party cookies blocked in every browser you support.
Draw the keys
Take one widget embedded on two unrelated sites and draw what the widget server receives from each site with:
- an unpartitioned
SameSite=Nonecookie - the
Partitionedcookie above - no cross-site cookie access at all
In the first case both sites send the same value. In the second, each site sends its own. In the third, nothing arrives and the widget must still work. If your design only survives case one, it’s already broken for many users.
Lesson completed