--forcepushed--fp
  • Home
  • Articles
  • Resources
  • Projects

Build smarter, ship faster, and stand out from the crowd.

Subscribe or follow on X for updates when new posts go live.

Follow on X

Implementing a Lightweight Propagating SSO with Ory Kratos

Implementing a Lightweight Propagating SSO with Ory Kratos

When multiple applications are migrated to a centralized authentication provider, one of the most difficult challenges often involves session propagation across domains rather than user identity itself.

A familiar example is Google’s ecosystem, where signing into Gmail automatically authenticates the user in YouTube, Drive, and Calendar. This is the behavior enabled by propagating single sign-on (SSO).

A similar pattern was required across several internal domains operating under different hostnames, all of which were transitioning to Ory Network (Kratos) for authentication.

Full OIDC federation or SAML-based solutions were unnecessary for the use case; the requirement was simply that users authenticate once and remain authenticated across all participating domains.

The mechanism described in this post outlines a lightweight SSO model implemented with Ory Kratos, using short-lived JWT-based handoffs to propagate session state—comparable in concept to Google’s multi-domain authentication propagation.

Background: The Ory Setup

Ory Kratos (hosted on Ory Network) was adopted as the authentication (AuthN) provider for login, registration, and password reset flows.

Authorization (AuthZ) remained implemented within each application’s own backend services.

The Existing In-House Flow

Before the migration, the process operated as follows:

  1. Users visited https://accounts.company.com to log in.
  2. The application hosted at that domain rendered the login UI, validated credentials, and set a session cookie.
  3. Additional internal domains (such as portal.company2.com or dashboard.company3.com) trusted that cookie through existing internal logic.

This model functioned adequately, but the move to Ory-managed identity required replacing the in-house authentication UI with redirect-based login flows while still ensuring that all existing application domains received their own session cookies.

The New Desired Flow

To maintain compatibility with existing bookmarks and entry points, https://accounts.company.com remained the user-facing login URL, though Ory would now control the authentication UI and issue sessions.

The following flow was designed:

  1. User initiates login
    A user visits https://accounts.company.com.

  2. Redirect to Ory login
    The application redirects the user to https://auth.company.com/login (an Ory-managed custom domain).

  3. User logs in at Ory
    After a successful login, Ory sets a secure session cookie for the parent domain (.company.com) and redirects back to accounts.company.com.

  4. App validates Ory session
    The accounts.company.com backend validates the Ory session cookie using the Ory API.

  5. Issue internal cookie and propagate
    After validation, the application generates a JWT containing the Ory session ID and other necessary context, then begins a propagation sequence by redirecting the user to each secondary domain with the JWT attached.

  6. Other domains validate and set cookies
    Each application in the chain validates the JWT, establishes a local session cookie, and redirects the user to the next domain.

  7. User lands at destination
    After the final redirect, the user arrives at the intended application already authenticated across all relevant domains.

This approach produces a brief sequence of redirects similar to Google’s inter-domain SSO propagation patterns.

Why Not OIDC or Oathkeeper?

Several alternatives were evaluated:

  • OIDC Federation: Would require each internal application to operate as an OIDC client and introduce significant additional complexity.
  • Ory Oathkeeper: Powerful for centralized access control but unnecessary for a limited set of internal services.
  • Custom session sharing: Simple to implement, aligned with operational timelines, and avoided unnecessary infrastructure overhead.

The chosen solution met the required reliability without adopting a full enterprise-scale identity federation.

Correcting the Context

The original authentication setup did not use Ory.

Identity, authentication, session management, and cookie issuance were all handled internally.

The purpose of this project was to offload these responsibilities to Ory while retaining usability and compatibility across existing applications.

Only the login and password reset experience at accounts.company.com changed from an internal implementation to a redirect-based entry point into Ory’s hosted flow.

AuthZ was intentionally left within existing applications; only AuthN was migrated to Ory.

Building a Propagating SSO Chain with Ory Kratos

Multi-domain internal platforms frequently struggle to provide users with consistent single sign-on behavior.

A shared expectation—popularized by ecosystems like Google’s—is that authentication should persist seamlessly across all properties.

During the transition to Ory Network for identity management, maintaining that experience across multiple company domains required a custom propagation mechanism.

This section describes how a propagating SSO pattern was created to ensure that all participating domains recognized the authenticated user, even though authentication itself was fully managed by Ory Kratos.

Background: In-House Authentication and Authorization

Prior to adoption of Ory, all authentication operations were implemented in-house:

  • Account creation, login, and password reset logic existed at https://accounts.company.com.
  • Session cookies were generated and validated directly by that application.
  • Authorization logic (AuthZ) remained local to each application domain.

Multiple related domains such as accounts.company.com, portal.company2.com, and dashboard.company3.com supported seamless transitions between them.

The migration to Ory introduced the challenge of maintaining this multi-domain session continuity while eliminating the internal authentication logic.

The Migration Goal

The fundamental goal was to discontinue internally managed authentication and rely entirely on Ory Kratos using Ory Network’s hosted UI.

Since users routinely navigated to https://accounts.company.com to initiate login, that entry point was preserved. Its new responsibility was simply to redirect to Ory, handle callback flows, and initiate the cross-domain SSO propagation sequence.

1. User Navigates to Login URL

https://accounts.company.com

If no valid local session is present, the application performs a redirect:

window.location.href = "https://auth.company.com/login?return_to=https://accounts.company.com/callback"

2. Ory Handles Authentication

The user completes authentication through Ory’s hosted interface.
Upon success, Ory sets a secure session cookie for .company.com and redirects back to the provided return URL.

3. App Verifies the Ory Session

The backend at accounts.company.com then validates the Ory session:

const response = await fetch('https://auth.company.com/sessions/whoami', {
  headers: { Cookie: req.headers.cookie || '' },
});
const session = await response.json();

If the session is valid, the application issues its own internal session cookie.

4. Begin the SSO Propagation Chain

Because cookies cannot cross root domain boundaries (e.g., company2.com or company3.com), a redirect sequence is initiated that carries a temporary JWT:

https://accounts.company2.com/sso?token=JWT

Each application validates the JWT, checks the Ory session, sets its local cookie, and redirects to the next domain.

The final redirect leads the user to their intended destination, fully authenticated.

Sequence Diagram

This diagram depicts the redirect chain and cookie-setting workflow used to propagate authentication state across multiple domains.

Security Considerations

Although the JWT is briefly visible in the browser address bar, the exposure risk was minimized through several controls.

The issuance model assumed fully internal, controlled domains, which made the approach acceptable for the environment.

Tokens were configured to be:

  • Short-lived (30 seconds)
  • Single-use
  • Signed using a shared HMAC secret

Example JWT Creation

import jwt from "jsonwebtoken";

const token = jwt.sign(
  { orySessionId: session.id },
  process.env.JWT_SECRET,
  { expiresIn: "30s" }
);

Example Verification

try {
  const decoded = jwt.verify(req.query.token, process.env.JWT_SECRET);
  // Re-check session validity with Ory here
} catch (e) {
  return res.status(401).send("Invalid or expired token");
}

How Google Handles SSO (and Why It’s Similar)

Google implements a similar propagation strategy:

  1. A user visits Gmail and is redirected to accounts.google.com.
  2. After authentication, cookies are set for .google.com along with background requests to domains such as accounts.youtube.com/SetSID.
  3. Each target domain sets its local cookies.
  4. A brief “Please wait…” screen appears during propagation.
  5. The user is authenticated across the entire Google ecosystem.

Logout operations occur using the same multi-domain propagation pattern.

The approach implemented here draws from that model but applies it to a much smaller set of internal domains, using redirect-driven JWT handoffs instead of background requests.

Why Not OIDC or Oathkeeper?

The evaluated alternatives were ultimately too heavyweight:

  • OIDC Federation: Would require full OIDC client implementations across all internal applications.
  • Ory Oathkeeper: Centralized but significantly more complex than necessary.

The lightweight JWT approach provided sufficient security while matching the simplicity and development timeline required.

Results and Future Improvements

The resulting system achieved the following:

  • Continued support for existing login URLs
  • Delegation of authentication and password reset flows to Ory
  • Seamless login propagation across all internal domains

Potential enhancements include:

  • iFrame-based silent cookie propagation
  • Centralized logout coordination
  • Incremental adoption of full OIDC clients as architecture evolves

Takeaway

Full OIDC federation is not required to achieve SSO-like behavior.

By combining Ory Kratos’ hosted login environment with a lightweight sequence of JWT-based redirects, it is possible to create a secure multi-domain authentication experience similar to larger platforms—without the overhead of implementing a full identity federation layer.

The design principle behind this solution is straightforward:

Adopt the simplest mechanism that satisfies the requirements, deliver quickly, and evolve only as the system’s needs grow.