Untitled

Cross-Subdomain Authentication Guide#

This document explains the architecture and implementation details for implementing secure, performant authentication across multiple subdomain projects using edge middleware and client-side data fetching.

Table of Contents#

  1. Architecture Overview
  2. Security Model
  3. Cookie Mechanics
  4. Edge Middleware Pattern
  5. Client-Side Data Fetching
  6. SWR Implementation Deep Dive
  7. CORS Configuration
  8. Complete Implementation
  9. Performance Characteristics
  10. Security Analysis

Architecture Overview#

The Pattern#

text

Key Benefits#

  • Fast: Edge middleware (~5ms) + static pages (CDN) + client hydration
  • Cheap: No SSR costs, minimal edge function costs
  • Secure: HttpOnly cookies + JWT validation + edge blocking
  • Simple: Centralized auth logic, minimal per-project code
  • Scalable: Static generation, CDN delivery

Security Model#

Defense in Depth#

text

When the auth service sets the JWT cookie:

http
http

Browser Behavior#

Cookie IS automatically sent to:

  • auth.gaz.codes/api/profile
  • project-a.gaz.codes/api/anything
  • project-b.gaz.codes/api/anything
  • ✅ Any subdomain of .gaz.codes

Cookie is NOT sent to:

  • otherdomain.com
  • gaz.codes.evil.com (not a subdomain)
  • ❌ HTTP sites (when Secure flag is set)

JavaScript CANNOT:

  • ❌ Read: document.cookie won't show HttpOnly cookies
  • ❌ Write: Cannot modify or delete HttpOnly cookies
  • ❌ Send to wrong domain: Browser enforces domain restriction

JavaScript CAN:

  • ✅ Trigger fetch requests that include the cookie (with credentials: 'include')
  • ✅ Receive data from API that validated the cookie

Client-Side Fetch Behavior#

typescript
typescript

What happens:

  1. Browser checks: Is auth.gaz.codes same-site as project-a.gaz.codes? ✓
  2. Browser checks: Does cookie domain .gaz.codes match? ✓
  3. Browser checks: Is connection HTTPS (Secure flag)? ✓
  4. Browser checks: Is SameSite policy satisfied? ✓
  5. Browser automatically attaches cookie to request
  6. JavaScript never sees the cookie value
  7. JavaScript receives the response data

Edge Middleware Pattern#

Shared Middleware Utility#

Create a reusable middleware factory in your shared packages:

typescript
typescript

Per-Project Implementation#

Each project uses the shared middleware with minimal configuration:

typescript
typescript

That's it! ~10 lines per project.

Latency Characteristics#

text

Client-Side Data Fetching#

Basic Pattern#

typescript
typescript

Timeline#

text

Basic Hook Implementation#

typescript
typescript

SWR Implementation Deep Dive#

Why SWR?#

SWR (stale-while-revalidate) is a React hooks library for data fetching that provides:

  1. Automatic caching: Fetch once, use everywhere
  2. Deduplication: Multiple components requesting same data = single network request
  3. Focus revalidation: Refresh data when user returns to tab
  4. Automatic retries: Network failures are retried automatically
  5. Optimistic updates: Update UI before server confirms
  6. Pagination support: Built-in infinite loading
  7. TypeScript support: Full type safety

Installation#

bash
bash

Basic SWR Implementation#

typescript
typescript

SWR Magic: Automatic Deduplication#

typescript
typescript

How it works:

  1. Component A calls useAuth() → SWR makes network request
  2. Component B calls useAuth() → SWR returns cached data (no network request)
  3. Component C calls useAuth() → SWR returns cached data (no network request)
  4. When data updates, ALL components re-render automatically

Advanced SWR Configuration#

typescript
typescript

SWR Configuration Explained#

Deduplication#

typescript
typescript
  • If useAuth() is called multiple times within 60s, only the first call makes a network request
  • Subsequent calls return cached data immediately
  • After 60s, the next call will make a fresh request

Revalidation Strategies#

typescript
typescript

User switches back to your tab → SWR automatically refreshes data to ensure it's current.

typescript
typescript

Network drops then reconnects → SWR refreshes data automatically.

typescript
typescript

If cached data is older than dedupingInterval → SWR fetches fresh data in background.

Retry Logic#

typescript
typescript

Behavior:

text

Useful for handling temporary network issues or server downtime.

Optimistic Updates#

typescript
typescript

SWR with Multiple Endpoints#

typescript
typescript

Global SWR Configuration#

typescript
typescript

SWR with TypeScript#

typescript
typescript

SWR Performance Comparison#

typescript
typescript

SWR Debugging#

typescript
typescript

CORS Configuration#

Your auth API must allow cross-subdomain requests:

typescript
typescript

Why each header:

Header Purpose
Access-Control-Allow-Origin Specifies which origin can access the resource
Access-Control-Allow-Credentials Allows cookies to be sent cross-origin
Access-Control-Allow-Methods HTTP methods the API supports
Access-Control-Allow-Headers Headers the API accepts
Access-Control-Max-Age How long browser caches preflight response

Complete Implementation#

Step 1: Install Dependencies#

bash
bash

Step 2: Create Shared JWT Utilities#

typescript
typescript

Step 3: Create Shared Auth Middleware#

typescript
typescript

Step 4: Create Shared Auth Hook with SWR#

typescript
typescript

Step 5: Implement in Projects#

typescript
typescript
typescript
typescript

Step 6: Configure CORS in Auth API#

typescript
typescript

Performance Characteristics#

Latency Breakdown#

text

Total time to interactive: ~250ms

Compare to SSR approach:

text

SSR time to interactive: ~400ms (60% slower)

Cost Analysis (Vercel Pro)#

Edge Middleware:

text

SSR:

text

Savings: ~94% cheaper with edge + static

Caching Benefits (with SWR)#

text

Security Analysis#

Attack Vectors & Mitigations#

1. XSS (Cross-Site Scripting)#

Attack: Inject JavaScript to steal auth token

javascript
javascript

Mitigation: HttpOnly cookie

text

2. CSRF (Cross-Site Request Forgery)#

Attack: Malicious site triggers authenticated request

html
html

Mitigation: SameSite=Lax cookie

text

3. Token Theft via MitM (Man-in-the-Middle)#

Attack: Intercept network traffic to steal token

Mitigation: Secure flag

text

4. Subdomain Takeover#

Attack: Attacker gains control of subdomain (e.g., old.gaz.codes), steals cookies

Mitigation: Monitor DNS, decommission unused subdomains

text

5. JWT Signature Forgery#

Attack: Craft fake JWT to impersonate user

Mitigation: Strong secret + verification

text

6. Replay Attacks#

Attack: Steal valid JWT, reuse to access account

Mitigation: Short expiry + refresh tokens

text

Security Checklist#

  • ✅ Cookie has HttpOnly flag
  • ✅ Cookie has Secure flag
  • ✅ Cookie has SameSite=Lax or Strict
  • ✅ Cookie domain is .gaz.codes (not broader)
  • ✅ JWT secret is 256+ bits, securely stored
  • ✅ JWT signature verified on every request
  • ✅ Access tokens expire within 1 hour
  • ✅ HTTPS enforced across all subdomains
  • ✅ CORS properly configured (specific origins only)
  • ✅ Unused subdomains decommissioned
  • ✅ Regular security audits

Troubleshooting#

Symptom: Client-side fetch returns 401, even though user is logged in

Causes:

  1. Missing credentials: 'include' in fetch
  2. CORS not configured properly
  3. Cookie domain mismatch

Debug:

typescript
typescript

Fix:

typescript
typescript

CORS Preflight Failures#

Symptom: OPTIONS request returns error, GET/POST never fires

Debug:

bash
bash

Expected response:

text

Middleware Redirect Loop#

Symptom: Endless redirects between project and auth

Cause: Middleware misconfigured, redirects authenticated users

Debug:

typescript
typescript

SWR Not Caching#

Symptom: Every component mount triggers new network request

Cause: SWR key is not stable (changes on every render)

Debug:

typescript
typescript

Additional Resources#

Summary#

This architecture provides:

Security: HttpOnly cookies, JWT validation, edge blocking ✅ Performance: Edge middleware (~5ms), static pages, SWR caching ✅ Cost: ~94% cheaper than SSR ✅ Developer Experience: Simple hook API, automatic caching, type safety ✅ Scalability: Static generation, CDN delivery, minimal server load

The combination of edge middleware for authentication gates and SWR for client-side data fetching provides the optimal balance of security, performance, and developer experience for cross-subdomain authentication.

Viewing as guest

Untitled | Knowledgebase