Authentication

Authentication lives entirely in the auth service, powered by BetterAuth. It is the trust anchor: it owns the user, session, account, and verification tables, issues httpOnly session cookies, and is the only service permitted to manage identity. Every other service verifies requests by forwarding cookies to it.

What you configure at init

When you keep the auth service in the wizard, you choose:

OptionChoices
OAuth providersGoogle, Apple, GitHub (any combination)
Email verificationon / off
Password reseton (default) / off
Two-factor authenticationon / off
Additional user fieldsextra columns on the user record
Admin dashboardon (default) / off

Email/password is always available. Selecting email verification or password reset wires in transactional email (Nodemailer); in test mode, sending is a no-op.

OAuth setup

OAuth client IDs and secrets are environment variables on the auth service — they ship as placeholders in .env.example:

# auth/backend/.env
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
APPLE_CLIENT_ID=...
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...

Sessions are httpOnly cookies

BetterAuth issues and rotates httpOnly session cookies — there is no client-held JWT to leak. A base service reads the principal by calling /api/auth/get-session; it never decodes a token itself. Native clients that can't carry cookies use the flexible flavor's device-session token instead.

The admin dashboard

With the dashboard enabled, the auth service ships a Next.js admin app on port :3333 — sign in, list users, manage roles, and delete users out of the box. It doubles as a reference implementation for consuming the auth backend from a stackr web app.

Roles

User roles drive the role-gated middleware flavor: a role-gated service admits only users holding one of its allowed roles (with admin always permitted). You assign roles from the admin dashboard.

Provisioning into a service

A user authenticated against auth may not yet have a record in a given base service. Each user carries a has<Service>Account flag; on the user's first authenticated call, a provisioning service creates the local record and flips the flag via POST /api/auth/provision. See Cross-Service Auth.

Identity has exactly one owner

Only the auth service may declare user, session, account, or verification tables. This is enforced by ast-grep and check:auth-tables, not just convention.