Skip to content
Ashish.
All posts
Diagram illustrating cross-domain cookie sharing and Same-Origin Policy boundaries.
6 min readBackendBackend developers, architectsFeatured#sso#cookies#authentication#security#web-development#cross-domain#backend

SSO With Cookies Across Multiple Domains

Explore how to implement Single Sign-On using cookies across multiple domains, addressing cross-domain challenges and third-party cookie restrictions.

By Ashish KumarPart 2 of Session, Logout, and SSO Mechanics

This is Part 2 of the Session, Logout, and SSO Mechanics series.

Implementing Single Sign-On (SSO) using cookies is one of the most common yet misunderstood patterns in web architecture. Developers often assume that because a user logs in once, the authentication state should automatically propagate to all associated services. However, the browser’s Same-Origin Policy (SOP) creates a hard boundary that prevents service-a.com from reading cookies set by service-b.com. To achieve SSO across multiple domains, you must navigate two distinct technical realities: the cooperative model for subdomains and the adversarial model for arbitrary domains.

The Subdomain Strategy: Shared Context

The simplest form of cross-domain SSO occurs when your applications share a common parent domain. For example, if you operate app.example.com and api.example.com, you can leverage the Domain attribute of the Set-Cookie header to create a shared cookie scope across subdomains.

When the Identity Provider (IdP) at auth.example.com authenticates a user, it sets an sso cookie:

Set-Cookie: session_id=abc123; Domain=.example.com; Path=/; Secure; HttpOnly; SameSite=Lax

The critical component here is Domain=.example.com. The leading dot indicates that this cookie is valid for example.com and all its subdomain instances (app.example.com, api.example.com, etc.). When app.example.com makes a request, the browser automatically attaches this cookie because the request’s host is a subdomain of the cookie’s domain.

It is crucial to distinguish between access control and transport mechanism. The Same-Origin Policy (SOP) prevents JavaScript running on one origin from reading the cookie value stored by another. However, SOP does not prevent the browser from attaching the cookie to HTTP requests. If the Domain and SameSite attributes allow it, the browser includes the cookie in the Cookie header of outgoing requests, regardless of whether the script has read access to it.

This mechanism works because the browser considers these requests to be within the same "site" context for cookie storage purposes. However, this strategy has strict limitations. It only works if you control all the subdomains. You cannot use this method to share cookies between company.com and partner.com.

Furthermore, the SameSite attribute plays a crucial role in how these cookies are transmitted during cross-site requests. If SameSite=Lax (the default in most browsers), the cookie is sent only on top-level navigation (e.g., clicking a link from partner.com to app.company.com). It is not sent with cross-site requests initiated by scripts (like fetch or XMLHttpRequest). For APIs, you must ensure your frontend explicitly handles the lack of automatic cookie attachment, often by switching to token-based authentication after the initial subdomain cookie exchange.

The Arbitrary Domain Barrier

When you attempt to implement cross domain sso between unrelated domains, such as login.myapp.com and dashboard.thirdparty.com, the Domain attribute fails. Browsers enforce the Same-Origin Policy, which dictates that a cookie set by login.myapp.com is inaccessible to dashboard.thirdparty.com.

If dashboard.thirdparty.com attempts to read document.cookie, it will see no session data from login.myapp.com. This is a security feature, not a bug. It prevents malicious scripts on one domain from stealing session tokens from another.

Consequently, true cross domain sso cannot rely on a single cookie being readable by both domains. Instead, it requires a mechanism to transfer the authentication state from the IdP domain to the client domain without exposing the raw cookie to the client script.

The Token Exchange Workaround

Historically, the standard workaround for cross domain sso involved a hidden iframe or popup window. However, this pattern is increasingly broken by modern browser security features like Safari’s Intelligent Tracking Prevention (ITP) and Chrome’s third-party cookie deprecation. These mechanisms restrict the persistence and visibility of cookies in cross-site iframe contexts, making this approach unreliable without specific workarounds.

The legacy mechanism attempted to function as follows:

  1. The client app redirects the user to auth.idp.com/login.
  2. The user authenticates, and auth.idp.com sets a session cookie.
  3. The IdP redirects back to a callback URL on client.app.com, but this redirect happens via a hidden iframe or a popup window.
  4. Inside this iframe, the IdP serves a JavaScript payload.
  5. This script cannot send the raw cookie value directly to the parent window via AJAX or variable sharing due to SOP isolation between the iframe and the parent.
  6. Instead, the script requests a short-lived token from the IdP’s token endpoint (often via a redirect or a specific API call within the iframe context).
  7. The script uses window.parent.postMessage() to send this token to the main client.app.com window.
  8. client.app.com receives the token and stores it (typically in memory or localStorage) for subsequent API calls.

This approach worked in older browsers because the iframe could maintain its own cookie state independently. The token exchange was a first-party request from the iframe to the IdP. The final token was then passed to the client domain, where it was stored as a first-party artifact (not a cookie), bypassing the cross-domain cookie restriction. Explicitly, the raw cookie value is never transferred to the parent window's JavaScript context.

However, this method is fragile. It relies on postMessage for inter-window communication, which can be intercepted if not carefully scoped. It also breaks easily if the IdP changes its response format or if the client app is embedded in an iframe itself, creating nested context issues.

The landscape of cross-domain SSO is shifting dramatically due to the deprecation of third party cookies. Major browsers, including Safari (via Intelligent Tracking Prevention) and Chrome (via the Privacy Sandbox), are progressively blocking or restricting the ability of third party cookies to persist across sessions.

In the context of SSO, this means that if your IdP sets an sso cookie as a third-party artifact (i.e., the cookie domain does not match the top-level navigation domain), the browser may delete it immediately or limit its lifetime. This breaks the hidden iframe pattern described above, as the session cookie on the IdP may not survive long enough to be exchanged.

Moreover, modern browsers are increasingly treating cross-site iframes as isolated contexts, further limiting the ability to communicate state between the IdP and the client app.

Given the fragility of cookie-based cross-domain SSO, the industry standard has shifted toward OpenID Connect (OIDC) with Proof Key for Code Exchange (PKCE). This flow does not rely on cross-domain cookies at all.

  1. The client app redirects the user to the IdP.
  2. The user authenticates on the IdP domain.
  3. The IdP redirects back to the client app with an authorization code.
  4. The client app exchanges this code for an ID token and access token directly from the IdP’s token endpoint.
  5. The client app stores the tokens locally.

This flow is robust because it treats the token exchange as a first-party API call after the redirect. It does not require the browser to share cookies between domains. It is also more secure, as it avoids the risks associated with storing session cookies in cross-domain contexts and leverages short-lived tokens.

While cookie-based SSO still works for subdomains, it is not a scalable solution for arbitrary domains in the modern web. Architects should prioritize OIDC/PKCE for new implementations, reserving cookie-sharing strategies only for tightly controlled subdomain ecosystems where they are explicitly supported and maintained.

Conclusion

Implementing SSO across multiple domains requires a nuanced understanding of browser security policies. While subdomain cookie sharing offers a straightforward solution for controlled environments, arbitrary domain SSO demands more complex workarounds like token exchanges. However, the ongoing deprecation of third-party cookies renders these legacy patterns increasingly unreliable. For modern architectures, adopting OIDC with PKCE provides a secure, future-proof alternative that aligns with evolving browser standards.

Related posts