Skip to content
Misar.io

How to Build Cross-Domain SSO Across Multiple Apps

All articles
Guide

How to Build Cross-Domain SSO Across Multiple Apps

Single sign-on (SSO) is the difference between a user typing one set of credentials and accessing every app they need, versus repeatedly logging in to each service—and then calling support when they forget a password. Wh

Misar Team·Dec 28, 2026·10 min read
Table of Contents

Single sign-on (SSO) is the difference between a user typing one set of credentials and accessing every app they need, versus repeatedly logging in to each service—and then calling support when they forget a password. When those apps live on different domains, SSO suddenly feels impossible. Cookies don’t cross origins, browsers block iframes, and identity tokens become a liability instead of an asset. The Misar team has helped dozens of engineering teams master this exact challenge, turning fragmented authentication into a seamless experience without compromising security. In this post, we’ll share what we’ve learned, the architecture we recommend, and how to implement it using MisarIO’s ecosystem—so your users stay logged in across every corner of your digital ecosystem.

Why Cross-Domain SSO Feels Impossible (And How to Fix It)

Cross-domain SSO breaks two fundamental assumptions in web security: that cookies can be shared across origins, and that tokens can safely travel between untrusted contexts. When your CRM, dashboard, and mobile app live on app.example.com, api.example.com, and mobile.example.net, browsers refuse to share session cookies, CORS policies block token forwarding, and identity brokers become critical infrastructure.

The common pitfalls are easy to spot in hindsight:

  • Cookie isolation: Browsers enforce SameSite=Lax by default, meaning session cookies set on app.example.com aren’t sent when a user visits api.example.com.
  • Token leakage: Passing JWTs in URLs or postMessage channels risks exposure in logs, browser history, or cross-origin iframes.
  • CORS misconfigurations: APIs reject Authorization headers from domains that aren’t explicitly allowed, breaking token exchange flows.
  • Session synchronization: Logging out of one app must invalidate sessions across all apps, which is hard when cookies and tokens are siloed.

At Misar, we’ve seen teams waste months trying to shoehorn OAuth into every corner of their stack—only to realize the protocol wasn’t designed for this scenario. Instead, we use identity federation via a central broker that handles token translation, session synchronization, and cross-domain consent. This approach scales across hundreds of apps and domains while keeping security auditors happy.

The MisarIO Identity Broker Pattern

Our recommended architecture is built on three pillars: a central identity broker, short-lived tokens, and secure cross-domain communication. Here’s how it works in practice:

  • Broker sits at a neutral origin (e.g., auth.misar.io)
  • Apps register as clients with the broker, specifying allowed redirect URIs and token scopes
  • User authenticates once at the broker, which issues a session cookie scoped to auth.misar.io
  • Apps request tokens via postMessage or a hidden iframe, using the broker’s /token endpoint
  • Tokens are short-lived (typically 5–15 minutes) and refreshed silently via /refresh

This design solves the cookie problem because the broker’s session cookie lives on its own origin, while apps remain isolated. Tokens are never exposed to the user’s browser history, and refresh tokens are stored in Secure, HttpOnly cookies on the broker’s domain—preventing JavaScript theft.

Broker Configuration Example (MisarIO)

``yaml

broker-config.yaml

clients:

  • id: "crm-app"

redirect_uris: ["https://app.example.com/auth/callback"]

scopes: ["profile", "crm:read"]

token_ttl: 600 # 10 minutes

refresh_ttl: 86400 # 1 day

  • id: "mobile-app"

redirect_uris: ["misar://auth/callback"]

scopes: ["profile", "api:write"]

token_ttl: 300 # 5 minutes

`

The broker handles token translation—so your CRM app receives a JWT with sub: "user123" and scope: "profile", while your mobile app gets a different token with scope: "api:write". This granularity is critical when apps need different levels of access.

Implementing Cross-Domain SSO in Three Steps

Adopting this pattern doesn’t require a rewrite of your apps. Here’s a pragmatic, step-by-step guide based on our work with customers across finance, healthcare, and SaaS.

Step 1: Deploy the MisarIO Identity Broker

Start by hosting the broker at a stable, neutral origin. MisarIO offers a managed broker service, or you can self-host it as a Docker container with a single YAML config file.

`bash

docker run -d \

-p 8080:8080 \

-v ./broker-config.yaml:/config.yaml \

misar/identity-broker:latest

`

Key requirements:

  • The broker must use HTTPS with a valid certificate
  • It must support CORS for your app domains
  • It should expose /authorize, /token, and /userinfo endpoints

Once deployed, register each of your apps as OAuth clients in the broker’s admin UI or config file. Be strict with redirect URIs—wildcard domains are a common source of token leakage.

Step 2: Modify Your Apps to Use the Broker

Each app needs three small changes:

  • Replace local auth logic with a call to the broker’s /authorize endpoint
  • Intercept token exchange using postMessage or a hidden iframe
  • Store tokens securely—never in localStorage or sessionStorage

Frontend (React) Example

`tsx

// App.tsx

import { useEffect } from 'react';

import { useAuth } from '@misar/auth-react';

function App() {

const { token, login, logout } = useAuth({

brokerUrl: 'https://auth.misar.io',

clientId: 'crm-app',

scopes: ['profile', 'crm:read'],

});

if (!token) {

return Sign in with Misar;

}

return (

Welcome, {token.sub}

Sign out

);

}

`

The @misar/auth-react library handles:

  • Redirecting to /authorize
  • Opening a child window to the broker
  • Listening for postMessage tokens
  • Storing tokens in memory (not localStorage)
  • Refreshing tokens silently

For mobile apps, use deep links instead of redirects:

`swift

// iOS Swift

let authUrl = URL(string: "https://auth.misar.io/authorize?client_id=crm-app&redirect_uri=misar://auth/callback")!

UIApplication.shared.open(authUrl)

`

Step 3: Enable Silent Refresh and Session Sync

Short-lived tokens are secure but annoying if users get logged out mid-session. Use silent refresh to keep them signed in:

`tsx

// Silent refresh in a hidden iframe

const refreshIframe = document.createElement('iframe');

refreshIframe.src = 'https://auth.misar.io/refresh?client_id=crm-app';

refreshIframe.style.display = 'none';

document.body.appendChild(refreshIframe);

`

Configure the broker to rotate refresh tokens on each use, and invalidate stale tokens server-side.

For session synchronization, the broker emits events to your apps via WebSockets or Server-Sent Events (SSE):

`yaml

broker-config.yaml

events:

enabled: true

endpoints:

  • "https://app.example.com/api/auth/session"
  • "https://dashboard.example.com/api/auth/session"

`

When a user logs out from their CRM, the broker broadcasts a LOGOUT event to all registered endpoints, forcing immediate session invalidation.

Handling Edge Cases and Security Gotchas

Even with a solid architecture, real-world apps introduce edge cases. Here’s what we’ve seen break—along with fixes we’ve validated with MisarIO customers.

Iframes and CORS Nightmares

If your app embeds another service in an iframe (e.g., a payment modal), the embedded app can’t read the broker’s cookies. Solution: use postMessage to request tokens instead.

`js

// Parent app

const iframe = document.querySelector('iframe');

iframe.contentWindow.postMessage(

{ type: 'GET_TOKEN', clientId: 'crm-app' },

'https://embedded.example.com'

);

// Embedded app

window.addEventListener('message', (event) => {

if (event.data.type === 'GET_TOKEN') {

const token = getTokenFromStore(); // From memory

event.source.postMessage({ type: 'TOKEN_RESPONSE', token }, event.origin);

}

});

`

Always validate event.origin to prevent token theft.

Mobile apps using custom URI schemes (e.g., myapp://auth/callback) can clash with other apps. Use Universal Links (iOS) or App Links (Android) instead:

`xml

`

This ensures the OS opens your app only when the broker redirects to a verified domain.

Token Scoping for Multi-Tenant Apps

In multi-tenant environments (e.g., a SaaS platform), tokens must include tenant context to prevent privilege escalation. Extend your JWT with a tenant_id:

`yaml

broker-config.yaml

scopes:

  • name: "tenant:read"

claims:

  • "tenant_id"
  • name: "tenant:admin"

claims:

  • "tenant_id"
  • "role"

`

Your backend APIs should validate tenant_id and reject requests where it doesn’t match the user’s active context.

Browser Extensions and Privacy Modes

Privacy-focused users running extensions like uBlock or using Incognito mode can break token flows by blocking cross-origin requests. Test your implementation in these environments early. MisarIO’s broker includes fallback flows for users with strict privacy settings, such as:

  • Using localStorage for token storage when cookies are blocked (with CSP headers to prevent XSS)
  • Offering a "copy token" button for manual paste into apps

Scaling to Hundreds of Apps and Domains

As your ecosystem grows, manual client registration becomes unsustainable. Here’s how to automate and secure large-scale SSO:

Dynamic Client Registration

Let apps register themselves via API:

`bash

curl -X POST https://auth.misar.io/register \

-H "Authorization: Bearer system-token" \

-d '{

"client_name": "analytics-tool",

"redirect_uris": ["https://analytics.example.com/callback"],

"scopes": ["profile", "analytics:read"],

"token_ttl": 300

}'

`

Requires a system-level token with admin scope and strict rate limiting.

Domain Allowlisting with Wildcards

Allow subdomains dynamically:

`yaml

broker-config.yaml

allowed_domains:

  • "*.example.com"
  • "*.staging.example.net"
  • "app.misar.io"

``

Validate domains at token request time to prevent open redirectors.

Automated Token Rotation

Use short-lived tokens (5–

cross-domain-ssoauthenticationidentityweb-appsmisario
Enjoyed this article? Share it with others.

More to Read

View all posts
Guide

How to Train an AI Chatbot on Website Content Safely

Website content is one of the richest sources of information your business has. Every help article, FAQ, service description, and policy page is a direct line to your customers’ most pressing questions—yet most of this d

9 min read
Guide

E-commerce AI Assistants: Use Cases That Actually Drive Revenue

E-commerce is no longer just about transactions—it’s about personalized experiences, instant support, and frictionless journeys. Today’s shoppers expect more than just a website; they want a concierge that understands th

11 min read
Guide

What a Healthcare AI Assistant Needs Before Launch

Healthcare AI isn’t just about algorithms—it’s about trust. Patients, clinicians, and regulators all need to believe that your AI assistant will do more than talk; it will listen, remember, and act responsibly when it ma

12 min read
Guide

Website AI Chat Widgets: What Converts Better Than Generic Bots

Website AI chat widgets have become a staple for SaaS companies looking to engage visitors, answer questions, and drive conversions. Yet, most chat widgets still rely on generic, rule-based bots that frustrate users with

11 min read

Explore Misar AI Products

From AI-powered blogging to privacy-first email and developer tools — see how Misar AI can power your next project.

Stay in the loop

Follow our latest insights on AI, development, and product updates.

Get Updates