Sign-in
Email and social sign-in, real sessions, and a users table in your app's own database.
Accounts are what turn a demo into an app, and the thing most first projects get wrong. On Camplax, sign-in arrives connected to the database: users land in a real table, sessions are handled properly, and the rules that keep people to their own rows are on from the start.
What your app gets
- Email and password sign-in is on by default.
- Passkeys are on by default — a fingerprint, face or security key signs a user in, scoped to your app's domain.
- Magic links and two-factor codes are switches in the project settings.
- Google, GitHub and Apple sign-in when you add the provider's OAuth client credentials on the Providers tab.
- A users table you can query and join against — a user is a row, not a record in someone else's dashboard.
Your app serves the sign-in endpoints itself — under /auth on its own domain — using the sign-in library Camplax builds for it. Camplax supplies the pieces that make that safe: it injects BETTER_AUTH_SECRET (the signing secret), AUTH_PROVIDERS and AUTH_CLAIMS (which methods and session fields are on), plus DATABASE_URL and CAMPLAX_URL. You never set these by hand; they arrive with every deploy like the rest of the Secrets.
Where the data lives
Everything about your users — the user, session, account and verification tables — sits in your project's own Postgres database, the same one your tables are in. There is no third-party user pool to sync, and nothing about a user lives on a service you cannot query. When you delete the project, the identity data goes with it.
The Users page
The console's Users page is five views of one subject — the people who signed in to your app (the people who work on the app are under Teams, a different list):
| Tab | What it shows |
|---|---|
| People | Every registered user — name, email, verified, plan, banned — with ban, unban and delete actions |
| Sessions | Who is signed in right now: device, IP, last seen, expiry — sessions that change address mid-stream are flagged |
| Providers | Which sign-in methods are on, and where OAuth client credentials go |
| Test users | Throwaway accounts for trying your own sign-in — see below |
| Claims | The fields stamped onto each session when it is created |
Sessions
Sessions use HTTP-only cookies with rotation, so a stolen laptop is a revoked session in the console, not a breach. Session rows carry a snapshot of the user's claims — role and plan by default — taken when the session is created. Demote a user and the change applies when the session expires or is revoked; Claims is where you add your own (up to 32, snake_case keys, each reading a field off the user row).
Test users
For previews and poking at your own app, Test users generates up to 25 accounts at once — names, *@test.camplax.app addresses (mail never delivers), a free/pro plan mix, and a password you can sign in with. Test users are marked is_test in the table and hidden from the People list unless you ask for them; one click clears them, their sessions and their accounts together.
Managing users from code
Everything the page does is on the API under /v1/projects/:slug/users. Reads need a session or a project key with users:read; writes need users:admin (and destructive console actions are owner-only).
| Method | Path | What it does |
|---|---|---|
GET | /users | List users (up to 100; ?include_test=1 includes test accounts) |
GET | /users/stats | Total, banned and verified counts |
GET | /users/export.csv | Download the user list as CSV |
GET | /users/sessions | Live sessions with device, IP and flags |
DELETE | /users/sessions/:id | Revoke one session |
POST | /users/sessions/revoke-all | Revoke every session |
GET/PUT | /users/providers | Read/set which sign-in methods are on |
GET/PUT | /users/claims | Read/set session claim definitions |
GET/POST/DELETE | /users/test-users | List, generate or clear test accounts |
POST | /users/:id/ban / /users/:id/unban | Ban or restore a user |
POST | /users/:id/reset-password | Reserved — returns not-implemented today; send the reset through your app's own /auth flow instead |
DELETE | /users/:id | Delete the user, their sessions and their accounts |
Provider credentials are secrets, not settings — when you turn on Google, GitHub or Apple, the client id and secret are stored as AUTH_GOOGLE_CLIENT_ID/AUTH_GOOGLE_CLIENT_SECRET (and friends) in the vault, where Secrets rules apply.
Rows stay with their owners
Sign-in is what makes "your data" mean something. In the starter — and any Plax app — defineResource takes an ownerField, and every read, update and delete it serves is scoped to the signed-in user's id inside the query itself, not checked afterwards. The client cannot write that field; the server sets it from the session, and a row you cannot see is a 404, not an error.
The sign-in UI
You do not have to build the form. Paste-ready components ship with the CLI:
camplax add --list
camplax add sign-in-card sign-up-card magic-link-screen
Each add copies an editable component into your app — the markup is yours to keep.
Where the users go next
Sign-in is the same project as the database, storage and payments, so "is this person subscribed?" and "which files are theirs?" are columns and rules, not API calls to another vendor. See Payments and File storage.
Under the hood: sign-in is Better Auth against your project's own database — no third-party user pool.