How do I share authentication cookies between two domains?
Short answer
You can’t. A browser sends a cookie only to the host that set it, or to that domain and its subdomains when the cookie has a Domain attribute, and no attribute adds a second domain. Workarounds built on third-party cookies fail in Safari and Firefox. Give each domain its own cookie instead, and share the sign-in through a central login, which is how loginos works.
You sign people in on example.com, and you want example.net to see the same authentication cookie, so nobody signs in twice. The second domain might be a new brand, a country domain, or your API on another host. However you set the cookie, example.net won’t receive it, and no browser offers an attribute that changes that.
Below is how cookie scoping works, why the features that look like workarounds aren’t, and what to build instead.
How does a browser decide where to send a cookie?
Every cookie has a scope, set by the server that creates it:
- Host-only cookie. Without a
Domainattribute, the browser sends the cookie back only to the exact host that set it. A cookie fromapp.example.comdoesn’t reachexample.comorshop.example.com. - Domain cookie. With
Domain=example.com, the browser sends the cookie toexample.comand to every subdomain. A leading dot, as in.example.com, is ignored today.
The Domain value must be the server’s own domain or one of its parents. A response from app.example.com may set Domain=example.com. If it names example.net, the browser ignores the whole cookie (RFC 6265, section 5.3). A cookie can name only one domain, and the port plays no part.
# Host-only: sent back to app.example.com only
Set-Cookie: __Host-session=abc; Path=/; Secure; HttpOnly; SameSite=Lax
# Domain cookie: sent to example.com and all of its subdomains
Set-Cookie: session=abc; Domain=example.com; Path=/; Secure; HttpOnly; SameSite=Lax
# Ignored when example.com sends it: a server can't set cookies for another domain
Set-Cookie: session=abc; Domain=example.net; Path=/; Secure; HttpOnlyThe __Host- prefix makes the browser enforce host-only scope. It accepts such a cookie only with Secure, Path=/ and no Domain, and all major browsers support it.
Why can’t example.com and example.net ever share a cookie?
Browsers group hosts into sites. A site is a registrable domain: one entry from the public suffix list plus the label just before it. com, net and co.uk are public suffixes, so example.com, example.net and example.co.uk are three separate sites. Nothing in the cookie rules joins two sites.
The list keeps cookies from spreading too far. Without it, a site could set a cookie for all of co.uk, and every site under it would receive it. Browsers refuse a Domain attribute that is a public suffix.
The list also includes hosting platforms where strangers get subdomains, such as github.io, vercel.app, netlify.app and pages.dev. For a browser, alice.github.io and bob.github.io are as separate as example.com and example.net, even though their names look like subdomains of one domain.
What does SameSite do, and does SameSite=None help?
SameSite decides whether a cookie travels with requests that start on another site. It never sends a cookie to a different domain.
| Value | Sent with requests that start on another site? |
|---|---|
Strict | Never |
Lax | Only on top-level navigations with a safe method, like following a link |
None | Always. Requires Secure. |
Chrome and Edge treat a cookie without SameSite as Lax, since Chrome 80 and Edge 86. Firefox and Safari don’t, so set the attribute yourself.
SameSite=None is often mistaken for a sharing switch. Say a page on example.net embeds an iframe from example.com, or calls it with fetch and credentials: "include". With SameSite=None, the browser may attach example.com’s cookie to that request, which goes to example.com. Code on example.net still never sees the cookie, and Safari and Firefox now block or partition exactly this kind of third-party cookie.
One rule for sign-in flows: keep the cookie that holds your state and PKCE values at SameSite=Lax. The way back from the identity provider is a navigation that starts on another site, and browsers don’t send a Strict cookie on it.
Which browsers block third-party cookies in 2026?
A third-party cookie goes with a request to a site other than the one in the address bar, for example from an iframe. Safari and Firefox stop them from working across sites by default, while Chrome and Edge still allow them.
| Browser | Third-party cookies by default | Partitioned cookies (CHIPS) | Storage Access API |
|---|---|---|---|
| Safari | Blocked, all of them, since Safari 13.1 (March 2020) | Since Safari 26.2 | Since Safari 11.1 |
| Firefox | Partitioned: one cookie jar for each site, since Firefox 103 (2022) | Since Firefox 141 | Since Firefox 65 |
| Chrome | Allowed. Blocked in Incognito, and people can block them in settings | Since Chrome 114 | Since Chrome 119 |
| Edge | Allowed, except for known trackers | Since Edge 114 | Since Edge 85 |
- Safari has no exceptions. The only way back in is the Storage Access API, plus a temporary fix for some popups.
- Firefox calls its version Total Cookie Protection. A cookie that
example.comsets insideexample.netlands inexample.net’s jar, soexample.comcan’t recognize the visitor there. Its temporary exceptions for some popups and redirects shouldn’t be relied on, MDN warns. - Chrome keeps them. Google gave up phasing them out, and in April 2025 said people will keep choosing in Chrome’s settings. In October 2025 it announced the retirement of most Privacy Sandbox APIs, including Related Website Sets.
- Edge blocks storage only for trackers on its lists, with its default tracking prevention, Balanced.
A login that depends on third-party cookies fails quietly for everyone on Safari and Firefox, and for Chrome users who turned them off or browse in Incognito.
Do partitioned cookies or the Storage Access API solve it?
No. Both work as designed, and the design rules out login sharing.
Partitioned cookies (CHIPS, Cookies Having Independent Partitioned State) use a Partitioned attribute. The browser files such a cookie under two keys: the host that set it and the top-level site in the address bar. A cookie that auth.example.com sets inside example.net exists only under example.net, and inside example.org it starts empty. Partitioning serves embeds that need their own state on each site, like a chat widget, and deliberately blocks recognition across sites.
The Storage Access API lets an iframe ask for its normal, unpartitioned cookies with document.requestStorageAccess(). Its rules make it a poor fit for sign-in:
- The request must follow a click or tap inside the iframe, and the browser may show a prompt.
- Browsers can refuse it when the person hasn’t recently used the embedded site as a top-level page. In Firefox, recently means 30 days.
- A grant covers one pair of sites, the top-level one and the embedded one, and ends after about 30 days without interaction.
So the API can’t tell your page on load whether someone is signed in. After a click, a redirect or a popup does the same job without an iframe.
What should you do instead?
Match the fix to your setup:
- Subdomains of one domain, like
app.example.comandshop.example.com: one cookie withDomain=example.comworks across all of them. Every subdomain then receives the session, so keep anything that runs other people’s code, like user content, on a separate domain. - A frontend and an API on different sites: serve the API from a subdomain of the frontend’s domain, like
api.example.com, or proxy API calls through the frontend’s own domain. The session cookie is then first-party. - Different domains: share the sign-in, not the cookie. A central login, an OpenID Connect identity provider, keeps a first-party cookie on its own domain, and each of your domains sets its own cookie after a short redirect. How do I share a login session across multiple domains? compares the options, and How do I implement single sign-on across different domains? builds it step by step.
FedCM (Federated Credential Management) is the browser API designed for sign-in across sites without third-party cookies. Chrome and Edge support it from version 108, and Firefox and Safari don’t. How does FedCM work and how do I use it? explains it.
How loginos does it
loginos is a central login for one product on many domains, and it never asks your domains to share a cookie. You add every domain to one platform, with no limit, and they all share one pool of people (Domains).
During a sign-in, loginos is the page in the address bar, so it reads its own first-party cookie. Your domain gets a one-time code, exchanges it on your server, and sets its own host-only cookie:
// In your callback, after the code exchange (see the quickstart)
const name = process.env.NODE_ENV === "production" ? "__Host-session" : "session"; // __Host- needs HTTPS
const done = NextResponse.redirect(new URL("/", req.url));
done.cookies.set(name, await createSession(user.sub), { // createSession: your own
httpOnly: true, // no JavaScript access
secure: true,
sameSite: "lax", // sent on links from other sites, not on their iframes or posts
path: "/", // and no domain: this host only
maxAge: 60 * 60 * 24 * 7, // your choice: loginos tokens last an hour, your session doesn't have to
});
return done;In Chrome and Edge, “Continue as” signs returning members in through FedCM, on your own page, without a redirect or a third-party cookie. Other browsers open a small loginos window after a click. The quickstart has the complete routes.
Frequently asked questions
Can I share cookies between subdomains?
Yes. A cookie set with Domain=example.com is sent to example.com and every subdomain, such as app.example.com and shop.example.com. The subdomains must share one registrable domain, and the parent can’t be a public suffix like github.io.
Can JavaScript on one domain read another domain’s cookies?
No. document.cookie only shows cookies that the browser would send to the current page’s host, and never HttpOnly ones. Code on example.net can’t read anything that example.com stored.
Why does my login cookie work in Chrome but not in Safari?
Usually because your frontend and your API run on different sites, for example myapp.vercel.app and myapi.onrender.com. The API’s cookie is then a third-party cookie, which Safari blocks and Chrome still allows by default. Serve the API from your frontend’s domain, or proxy it there.
Will Chrome block third-party cookies?
Not by default, as things stand in 2026. Google gave up phasing them out, and people choose in Chrome’s settings. Incognito windows block them, and anyone can turn them off, so design as if they are blocked.
Can I declare my domains as related so they share cookies?
Not in practice. Chrome’s Related Website Sets let a declared group of domains get storage access more easily, and Google announced their retirement in October 2025. Firefox and Safari never supported them, and even inside a set, each cookie stayed with its own domain.
One account for every domain you run
loginos is an OpenID Connect provider with passkeys, a user pool shared by all of your domains, roles in every token, and account linking for the users you already have. Add your platform and its domains in a few minutes.
Keep reading
- Sign-in across domainsHow do I share a login session across multiple domains?You can’t share a session cookie between two different domains, because browsers only send a cookie to the domain that set it. Instead, each domain keeps its own session and gets it from one central login, an OpenID Connect provider. Someone who is already signed in there is sent straight back with a one-time code, without seeing a form.6 min read
- Sign-in across domainsHow do I implement single sign-on across different domains?Use one OpenID Connect provider for all of your domains, and register each domain’s callback URL with it. On every domain, add a route that redirects to the provider with state and PKCE, and a callback that checks state, exchanges the code on your server and starts that domain’s own session. People signed in on one domain then pass through the others without a form.8 min read
- Sign-in across domainsHow can users log in once and stay logged in on all my websites?Keep one long-lived session at a central login, an OpenID Connect provider, and a separate session on each of your websites. When a site has no session, it asks the provider silently with prompt=none, and people who are signed in there come straight back without a form. Each site renews its own session this way, so people stay logged in everywhere until the central session ends.8 min read
- One-tap sign-inHow does FedCM work and how do I use it?FedCM (Federated Credential Management) is a browser API for signing in with an identity provider without third-party cookies or redirects. Your page calls navigator.credentials.get with the provider’s config URL; the browser fetches the accounts itself, shows a “Continue as” prompt, and returns a token only after the person continues. Chrome and Edge support it, and loginos is one such provider.8 min read