# How do I share authentication cookies between two domains?

> 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 `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](https://www.rfc-editor.org/rfc/rfc6265#section-5.3)). A cookie can name only one domain, and the port plays no part.

```http title="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.

## 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](https://publicsuffix.org/) 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.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?](https://loginos.io/answers/share-login-session-across-domains.md) compares the options, and [How do I implement single sign-on across different domains?](https://loginos.io/answers/single-sign-on-across-domains.md) 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?](https://loginos.io/answers/how-fedcm-works.md) 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](https://loginos.io/docs/domains.md)).

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:

```ts title="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;
```

In Chrome and Edge, [“Continue as”](https://loginos.io/docs/continue-as.md) 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](https://loginos.io/docs/quickstart.md) 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.

---

Updated 2026-10-14. Web page: https://loginos.io/answers/share-cookies-between-domains
