Auth Flow
Auth & sessions
Authentication is powered by Better Auth with a Drizzle adapter on Postgres. Session cookies are integrated with TanStack Start via the tanstackStartCookies() plugin (must be last in the plugin list).
Server entrypoint
packages/server/src/auth.ts—betterAuth({ ... })instance.- Required env:
AUTH_SECRET,DATABASE_URL,BETTER_AUTH_URL(defaults tohttp://localhost:3001if omitted). BETTER_AUTH_TRUSTED_ORIGINS— comma-separated; merged with trimming forredirectTo/ OAuth callbacks across hosts.- Optional
BETTER_AUTH_COOKIE_DOMAIN—advanced.defaultCookieAttributes.domainfor cross-subdomain cookies.
Features enabled
- Email + password with optional
AUTH_REQUIRE_EMAIL_VERIFICATION=1(only after Resend /EMAIL_FROMwork). - Password reset and email verification hooks call
packages/server/src/email/send-auth-email.ts(Resend when configured; otherwise dev console logs in development). - Social providers — built from env via
packages/server/src/auth/social-provider-registry.ts(Google/GitHub when ids and secrets are set). - User field mapping — Better Auth
image→ DB columnavatar_url.
Session behavior
- expiresIn — 30 days of inactivity.
- updateAge — refresh if session older than 1 day.
- cookieCache — session payload cached in cookie for 5 minutes (Better Auth option).
Database hooks
On user create, after signup:
- Logs analytics (
USER_SIGNUPwith OAuth provider when applicable). - Creates a personal organization (slug from email prefix + random suffix) and an owner
organization_membersrow. - Logs
ORG_CREATED.
Admin plugin and impersonation
admin()plugin withadminUserIdsfromADMIN_USER_IDSenv (packages/server/src/admin/admin-config.ts).- Impersonation session duration: 1 hour (
impersonationSessionDuration: 60 * 60). - Admin client usage from the product UI for impersonate/stop (see shared admin components).
Session for loaders and RPC
packages/server/src/auth-session.ts—getSessionserver function (dynamic imports to keep client bundles free ofpostgres).- Returns
SessionWithOrgs: user, organizations with roles, welcome onboarding flag, platform admin flag, and optional impersonation metadata (resolved fromsessions.impersonated_by).
Use this for “who is signed in” and org membership in route loaders and mutations.
Platform admin guard
packages/server/src/admin/admin-guard.ts—requirePlatformAdminensures a signed-in user is a platform admin; otherwise redirects to home or sign-in.
API route
- Product app serves Better Auth HTTP via TanStack Start API route (e.g.
/api/auth/*underapps/web).
Related
- System overview
- Environment variables
- Database schema —
users,sessions,accounts,verifications