Today Platform Web — Dev Docs
Architecture

Auth cookie current state

A current-state snapshot of cookie, domain, and auth relationships in today-platform-web. No target design, no migration plan.

Verified at commit a553ab705d8b7735d97e908e3a67dc17fe1842e1.

This note documents the current cookie, domain, and auth relationship in today-platform-web only. It is intentionally current-state only: no target-state design, no migration plan, and no new domains.

Current domain relationship in this repo

  • today.ai: main web app (apps/web)
  • admin.today.ai: admin app (apps/admin)
  • auth.today.ai: auth service origin resolved by resolveAuthBaseUrl()
  • api.today.ai: API origin resolved by resolveApiBaseUrl()

The same shape is used in dev docs with todayai.dev equivalents. The web repo treats auth and API as separate origins, then adds app-origin proxy routes where needed.

The main web app uses Better Auth against the app origin, not directly against auth.today.ai from the browser:

  • apps/web/src/lib/better-auth-client.ts: createAuthClient({ baseURL: betterAuthConfig.baseURL, fetchOptions: { credentials: 'include' } })
  • apps/web/src/lib/session-auth-client.ts: lightweight session client also points at betterAuthConfig.baseURL
  • apps/web/src/data/user/session-query.ts: session reads call authClient.getSession()

That app-origin auth traffic is proxied server-side to the auth service:

  • apps/web/src/app/api/auth/[...all]/route.ts: proxies /api/auth/* to ${AUTH_BASE_URL}/api/auth/*
  • apps/web/src/app/api/auth/[...all]/utils.ts: forwards incoming cookie, authorization, content-type, accept, user-agent, accept-language, and origin

/api/token also depends on the browser cookie being available on the app origin:

  • apps/web/src/hooks/use-session.ts: calls fetch('/api/token', { credentials: 'include' })
  • apps/web/src/app/api/token/route.ts: reads request.headers.get('cookie') and request.headers.get('authorization'), then forwards them to ${AUTH_BASE_URL}/api/token

In other words, the current apps/web flow assumes:

  1. The browser has a valid session cookie.
  2. That cookie is sent on requests to today.ai.
  3. The web app forwards that cookie to auth.today.ai through /api/auth/* and /api/token.

The current docs in this repo explicitly describe the shared-cookie assumption:

  • Auth interaction architecture: the social login callback lands on the auth origin, and even with a BFF proxy the session must remain visible after redirecting back to the app
  • Local development: documents the concrete dev flow where Google redirects to auth.todayai.dev, the auth server sets a cookie on .todayai.dev, and the browser later sends that cookie on app requests
  • Environment variables: repeats the same constraint and calls out cookie-domain alignment as required for login to keep working

This means the current web login flow is not purely "same-origin BFF only". The browser still visits the auth origin during social/OIDC redirects, and the repo documentation assumes the resulting session remains usable when the browser returns to the app origin.

The admin app mixes OIDC bearer tokens with the same app-origin proxy pattern:

  • apps/admin/src/lib/oidc-config.ts
    • authority is resolveAuthBaseUrl()
    • authorization_endpoint points directly to ${authority}/api/auth/oauth2/authorize
    • token_endpoint is proxied through ${appOrigin}/api/auth/token
    • userinfo_endpoint is proxied through ${appOrigin}/api/auth/oauth2/userinfo
  • apps/admin/src/data/user/session-query.ts: fetches /api/auth/oauth2/userinfo with Authorization: Bearer <access_token>

Admin proxy routes still forward cookies when present:

  • apps/admin/src/app/api/auth/[...all]/route.ts: proxies /api/auth/* to the auth service
  • apps/admin/src/app/api/auth/[...all]/utils.ts: forwards incoming cookie and authorization
  • apps/admin/src/app/api/token/route.ts: forwards incoming cookie and authorization to ${AUTH_BASE_URL}/api/token
  • apps/admin/src/hooks/use-session.ts: calls fetch('/api/token', { credentials: 'include', headers: { Authorization: ... } })

So the current admin picture is:

  • interactive login starts with OIDC redirects against the auth origin
  • user/session reads are bearer-token based
  • app-origin proxy routes still preserve cookie forwarding behavior instead of assuming a cookie-free model

Current-state conclusion

In the current web repo, /api/auth/* and /api/token are implemented as thin app-origin proxies to the auth service, and both preserve browser cookies when available. The main web app still depends directly on that session cookie path. The admin app is more bearer-token-oriented, but it has not removed cookie forwarding from the same proxy surface.

On this page