---
title: "Cookie Domain Mismatch After Migration Causes Silent Auth Loop"
aliases: [cookie-domain-auth-loop, cookie-domain-migration, auth-redirect-loop]
tags: [auth, cookies, migration, fastapi, debugging, gotcha]
sources:
  - "daily/2026-04-29.md"
created: 2026-04-29
updated: 2026-04-29
---

# Cookie Domain Mismatch After Migration Causes Silent Auth Loop

When a project is migrated to a new domain and `COOKIE_DOMAIN` is not updated, the browser silently drops the auth cookie set for the wrong domain. This manifests as an infinite redirect loop to `/login` with no visible error — one of the harder auth bugs to diagnose.

## Key Points

- `COOKIE_DOMAIN` mismatch causes silent cookie rejection by the browser — no 4xx, no JS error
- Symptom: page loads → immediately redirects to `/login` → repeat (infinite loop)
- Root cause: server sets `Set-Cookie: domain=old-domain.com`, browser on `new-domain.com` drops it silently
- After fixing `API_BASE_URL`, the frontend **must be rebuilt** — env vars are baked into the JS bundle at build time
- Double `/api/api/` in request URLs is a separate symptom: `API_BASE_URL` already includes `/api` AND frontend code appends another `/api` segment

## Details

### Symptom Pattern

```
User navigates to /dashboard
→ Frontend checks auth → calls /api/auth/me
→ Server returns 401 (no valid session cookie)
→ Frontend redirects to /login
→ User logs in → server issues cookie for wrong domain
→ Browser drops cookie silently
→ Next request: 401 again → redirect to /login → loop
```

No error appears in the console or server logs that clearly identifies the domain mismatch — the only signal is the redirect loop itself.

### Diagnosis Checklist

1. **Check `COOKIE_DOMAIN` in `.env`** — must match the current deployment domain
2. **Open DevTools → Application → Cookies** — does the cookie appear after login? If not, domain mismatch
3. **Check `API_BASE_URL` in `.env`** — if it ends with `/api`, don't add `/api` again in frontend code
4. **Rebuild frontend** after any env var change — Vite bakes vars into the bundle

### The Double `/api/api` Symptom

```env
# .env (wrong)
API_BASE_URL=https://optical-dev.oliver.solutions/video-accessibility/api
```

```typescript
// frontend code (also appends /api)
fetch(`${API_BASE_URL}/api/upload`)
// → results in: /video-accessibility/api/api/upload
```

Fix: either strip `/api` from `API_BASE_URL` or remove the extra `/api` from frontend call sites, then rebuild.

### Rebuild Requirement

```bash
# After fixing .env on the server:
cd /opt/video-accessibility/frontend
VITE_BASE_PATH=/video-accessibility npm run build
sudo cp -r dist/. /var/www/html/video-accessibility/
```

Old bundle continues serving the old `API_BASE_URL` until rebuilt — environment variables are NOT read at runtime in Vite SPAs.

## Related Concepts

- [[wiki/architecture/optical-dev-server-deploy]] — full optical-dev deploy pattern
- [[wiki/concepts/apache-proxypass-include-files-ignored]] — the Apache gotcha discovered in the same session
