Clerk Cross-Subdomain Authentication
Overview
HappyClient uses Clerk for authentication across multiple apps on subdomains:
hello.thehappyclient.com- Onboarding applibrary.thehappyclient.com- Video library appflow.thehappyclient.com- Branded video flow applinks.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:
| Cookie | Domain | Purpose |
|---|---|---|
__client | clerk.thehappyclient.com | Source of truth for auth state (shared!) |
__client_uat | .thehappyclient.com | User activity tracking (shared!) |
__session | hello.thehappyclient.com | Short-lived session token (per-app, auto-refreshed) |
When you visit any subdomain, Clerk.js:
- Checks the
__clientcookie on the FAPI domain - Validates the session
- Creates/refreshes the
__sessioncookie 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:
- Go to Clerk Dashboard (staging instance) → Configure → Domains
- Add custom domain:
clerk.staging.thehappyclient.com - Add DNS CNAME record pointing to Clerk
- Wait for verification
This requires a paid Clerk plan for production instances.
Troubleshooting
"User needs to login multiple times"
| Environment | Expected Behavior | Solution |
|---|---|---|
| Production | Login once, shared everywhere | Should work automatically. Check all apps use same Clerk keys. |
| Staging/Preview | Login per app | Expected limitation. Configure custom FAPI domain if needed. |
Verifying Cookie Configuration
- Open browser DevTools → Application → Cookies
- Look for
__clientor__client_uatcookies - Check the Domain column:
.thehappyclient.comorclerk.thehappyclient.com= ✅ Shared*.clerk.accounts.devor specific subdomain = ❌ Not shared
Technical Details
Clerk Apps
| Environment | Clerk Instance | FAPI Domain | Cross-Subdomain Auth |
|---|---|---|---|
| Production | HappyClient (Production) | clerk.thehappyclient.com | ✅ Works |
| Staging/Preview | HappyClient (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
- Clerk: How Clerk Works
- Clerk: Satellite Domains (for different ROOT domains, not needed for subdomains)
- Clerk: Cookie Documentation