All docs/Authentication

docs/architecture/clerk-subdomain-authentication.md

Clerk Cross-Subdomain Authentication

Overview

HappyClient uses Clerk for authentication across multiple apps on subdomains:

  • hello.thehappyclient.com - Onboarding app
  • library.thehappyclient.com - Video library app
  • flow.thehappyclient.com - Branded video flow app
  • links.thehappyclient.com - QR code links app

✅ Production: Single Sign-On Works Automatically

In production, users only need to log in once and their session is shared across all subdomains automatically.

Why It Works

Clerk uses a Frontend API (FAPI) domain to manage authentication state:

Production FAPI: clerk.thehappyclient.com

Since clerk.thehappyclient.com is on the same root domain as our apps (*.thehappyclient.com), the browser can share Clerk's authentication cookies across all subdomains.

How Clerk's cookies work:

CookieDomainPurpose
__clientclerk.thehappyclient.comSource of truth for auth state (shared!)
__client_uat.thehappyclient.comUser activity tracking (shared!)
__sessionhello.thehappyclient.comShort-lived session token (per-app, auto-refreshed)

When you visit any subdomain, Clerk.js:

  1. Checks the __client cookie on the FAPI domain
  2. Validates the session
  3. Creates/refreshes the __session cookie for that subdomain

No special configuration needed - just ensure all apps use the same Clerk publishable/secret keys.

❌ Staging/Preview: Login Required Per App

In staging and preview environments, users must log in separately on each subdomain.

Why It Doesn't Work

Our staging/preview Clerk app uses the default Clerk development domain:

Staging FAPI: absolute-tetra-58.clerk.accounts.dev  ❌ NOT on thehappyclient.com!

Since this domain is not on *.thehappyclient.com, browsers cannot share cookies between the Clerk FAPI and our apps. Each app gets isolated authentication.

Visual Explanation

PRODUCTION (works ✅)
┌─────────────────────────────────────────────────────────────┐
│                  .thehappyclient.com                        │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │    hello.    │  │   library.   │  │    flow.     │      │
│  │thehappyclient│  │thehappyclient│  │thehappyclient│      │
│  └──────────────┘  └──────────────┘  └──────────────┘      │
│                           ↑                                 │
│                    ┌──────────────┐                        │
│                    │    clerk.    │  ← FAPI on same domain │
│                    │thehappyclient│    Cookies shared! ✅   │
│                    └──────────────┘                        │
└─────────────────────────────────────────────────────────────┘

STAGING/PREVIEW (doesn't work ❌)
┌─────────────────────────────────────────────────────────────┐
│                  .thehappyclient.com                        │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │   staging.   │  │   staging.   │  │   staging.   │      │
│  │hello.thehappy│  │library.thehap│  │flow.thehappy │      │
│  └──────────────┘  └──────────────┘  └──────────────┘      │
└─────────────────────────────────────────────────────────────┘
                           ✗ No connection!
┌─────────────────────────────────────────────────────────────┐
│                   .clerk.accounts.dev                       │
│                    ┌──────────────┐                        │
│                    │absolute-tetra│  ← FAPI on DIFFERENT   │
│                    │   -58.clerk  │    domain!             │
│                    └──────────────┘    Cookies NOT shared ❌│
└─────────────────────────────────────────────────────────────┘

How to Fix Staging/Preview (Optional)

If cross-subdomain auth is needed in staging, configure a custom domain in the staging Clerk app:

  1. Go to Clerk Dashboard (staging instance) → Configure → Domains
  2. Add custom domain: clerk.staging.thehappyclient.com
  3. Add DNS CNAME record pointing to Clerk
  4. Wait for verification

This requires a paid Clerk plan for production instances.

Troubleshooting

"User needs to login multiple times"

EnvironmentExpected BehaviorSolution
ProductionLogin once, shared everywhereShould work automatically. Check all apps use same Clerk keys.
Staging/PreviewLogin per appExpected limitation. Configure custom FAPI domain if needed.

Verifying Cookie Configuration

  1. Open browser DevTools → Application → Cookies
  2. Look for __client or __client_uat cookies
  3. Check the Domain column:
    • .thehappyclient.com or clerk.thehappyclient.com = ✅ Shared
    • *.clerk.accounts.dev or specific subdomain = ❌ Not shared

Technical Details

Clerk Apps

EnvironmentClerk InstanceFAPI DomainCross-Subdomain Auth
ProductionHappyClient (Production)clerk.thehappyclient.com✅ Works
Staging/PreviewHappyClient (Development)*.clerk.accounts.dev❌ Limited

Required Environment Variables

All apps in the same environment must use identical keys:

# Same across all apps in production
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_live_xxxxx
CLERK_SECRET_KEY=sk_live_xxxxx

# Same across all apps in staging
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxxxx  
CLERK_SECRET_KEY=sk_test_xxxxx

References