loginos

How do I share authentication cookies between two domains?

loginos teamUpdated 7 min read

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.

Every cookie has a scope, set by the server that creates it:

  • Host-only cookie. Without a Domain attribute, the browser sends the cookie back only to the exact host that set it. A cookie from app.example.com doesn’t reach example.com or shop.example.com.
  • Domain cookie. With Domain=example.com, the browser sends the cookie to example.com and 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.

Set-Cookie
# 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; HttpOnly

The __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.

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.

ValueSent with requests that start on another site?
StrictNever
LaxOnly on top-level navigations with a safe method, like following a link
NoneAlways. 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.

BrowserThird-party cookies by defaultPartitioned cookies (CHIPS)Storage Access API
SafariBlocked, all of them, since Safari 13.1 (March 2020)Since Safari 26.2Since Safari 11.1
FirefoxPartitioned: one cookie jar for each site, since Firefox 103 (2022)Since Firefox 141Since Firefox 65
ChromeAllowed. Blocked in Incognito, and people can block them in settingsSince Chrome 114Since Chrome 119
EdgeAllowed, except for known trackersSince Edge 114Since 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.com sets inside example.net lands in example.net’s jar, so example.com can’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.com and shop.example.com: one cookie with Domain=example.com works 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:

Next.js
// 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;
Browser
Your server
loginos
1/6Your site sends the browser to loginos with your app key, a state and a PKCE challenge.

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.

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.

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

All answers