Files
zopu-code/docs/auth-proxy.md
-Puter bf2300a6be feat: same-origin auth via reverse proxy and secure cookies
Route /api/auth through the same origin in both dev and prod so
cookies stay first-party and the browser and React Router SSR share
one auth surface.

- Vite dev server proxies /api/auth to the Convex HTTP site.
- Better Auth uses secure cookies when the site URL is https.
- Add docs/auth-proxy.md documenting the required production ingress
  (Caddy/Traefik) and Convex SITE_URL / CONVEX_SITE_URL setup.
2026-07-29 19:32:26 +05:30

2.5 KiB

Auth Proxy — Production Ingress Requirement

The application uses same-origin authentication: the browser and React Router SSR both hit /api/auth/* on the public application domain. This keeps cookies first-party, avoids cross-origin credentials, and gives development and production the same API surface.

Required production route

At the public application domain, route:

Prefix Target
/api/auth/* Convex HTTP site
/* React Router frontend

Caddy

zopu.example.com {
    handle /api/auth/* {
        reverse_proxy https://befitting-dalmatian-161.convex.site {
            header_up Host befitting-dalmatian-161.convex.site
        }
    }

    handle {
        reverse_proxy frontend:3000
    }
}

Dokploy / Traefik

Create a higher-priority path router for /api/auth that forwards to the external Convex site URL. Ensure it:

  • Preserves the original browser Cookie header
  • Passes Set-Cookie responses back (rewrite domain if Convex emits an explicit one)
  • Preserves the original method and body
  • Forwards X-Forwarded-Host and X-Forwarded-Proto
  • Passes the full path unchanged (e.g. /api/auth/convex/token)
  • Does not cache auth responses
  • Allows OAuth callback routes under the same prefix

Convex environment

The Convex deployment SITE_URL must match the public origin users visit, not the Convex site URL:

# Production
npx convex env set SITE_URL 'https://zopu.example.com'

# Local
npx convex env set SITE_URL 'http://100.101.157.28:5173'

# Staging
npx convex env set SITE_URL 'https://zopu.cheaptricks.puter.wtf'

This value populates Better Auth's trustedOrigins. The Convex deployment also uses CONVEX_SITE_URL as the internal baseURL for route registration; that value is the HTTP site URL (e.g. https://befitting-dalmatian-161.convex.site).

Why same-origin

  1. First-party cookies. No SameSite=None, no third-party cookie restrictions.
  2. SSR consistency. The React Router server uses the same auth surface the browser sees; no cross-host credential translation.
  3. No CORS complexity. The browser talks only to its own origin.
  4. The reverse proxy handles the cross-host hop server-side.
  • Better Auth: Trusted Origins
  • apps/web/vite.config.ts — Vite dev proxy (/api/auth → Convex site)
  • packages/auth/src/web/auth-client.tswindow.location.origin
  • apps/web/src/lib/auth.server.ts — SSR token loader via request origin