Skip to content

Commit 57c6177

Browse files
authored
Merge pull request #558 from netzbegruenung/test-branch
Deploy: notebook search depth, dark mode, docs overview, and more
2 parents 60057d4 + 7cbb526 commit 57c6177

4,711 files changed

Lines changed: 944686 additions & 59072 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
---
2+
name: better-auth-best-practices
3+
description: Configure Better Auth server and client, set up database adapters, manage sessions, add plugins, and handle environment variables. Use when users mention Better Auth, betterauth, auth.ts, or need to set up TypeScript authentication with email/password, OAuth, or plugin configuration.
4+
---
5+
6+
# Better Auth Integration Guide
7+
8+
**Always consult [better-auth.com/docs](https://better-auth.com/docs) for code examples and latest API.**
9+
10+
---
11+
12+
## Setup Workflow
13+
14+
1. Install: `npm install better-auth`
15+
2. Set env vars: `BETTER_AUTH_SECRET` and `BETTER_AUTH_URL`
16+
3. Create `auth.ts` with database + config
17+
4. Create route handler for your framework
18+
5. Run `npx @better-auth/cli@latest migrate`
19+
6. Verify: call `GET /api/auth/ok` — should return `{ status: "ok" }`
20+
21+
---
22+
23+
## Quick Reference
24+
25+
### Environment Variables
26+
27+
- `BETTER_AUTH_SECRET` - Encryption secret (min 32 chars). Generate: `openssl rand -base64 32`
28+
- `BETTER_AUTH_URL` - Base URL (e.g., `https://example.com`)
29+
30+
Only define `baseURL`/`secret` in config if env vars are NOT set.
31+
32+
### File Location
33+
34+
CLI looks for `auth.ts` in: `./`, `./lib`, `./utils`, or under `./src`. Use `--config` for custom path.
35+
36+
### CLI Commands
37+
38+
- `npx @better-auth/cli@latest migrate` - Apply schema (built-in adapter)
39+
- `npx @better-auth/cli@latest generate` - Generate schema for Prisma/Drizzle
40+
- `npx @better-auth/cli mcp --cursor` - Add MCP to AI tools
41+
42+
**Re-run after adding/changing plugins.**
43+
44+
---
45+
46+
## Core Config Options
47+
48+
| Option | Notes |
49+
| ------------------ | ---------------------------------------------- |
50+
| `appName` | Optional display name |
51+
| `baseURL` | Only if `BETTER_AUTH_URL` not set |
52+
| `basePath` | Default `/api/auth`. Set `/` for root. |
53+
| `secret` | Only if `BETTER_AUTH_SECRET` not set |
54+
| `database` | Required for most features. See adapters docs. |
55+
| `secondaryStorage` | Redis/KV for sessions & rate limits |
56+
| `emailAndPassword` | `{ enabled: true }` to activate |
57+
| `socialProviders` | `{ google: { clientId, clientSecret }, ... }` |
58+
| `plugins` | Array of plugins |
59+
| `trustedOrigins` | CSRF whitelist |
60+
61+
---
62+
63+
## Database
64+
65+
**Direct connections:** Pass `pg.Pool`, `mysql2` pool, `better-sqlite3`, or `bun:sqlite` instance.
66+
67+
**ORM adapters:** Import from `better-auth/adapters/drizzle`, `better-auth/adapters/prisma`, `better-auth/adapters/mongodb`.
68+
69+
**Critical:** Better Auth uses adapter model names, NOT underlying table names. If Prisma model is `User` mapping to table `users`, use `modelName: "user"` (Prisma reference), not `"users"`.
70+
71+
---
72+
73+
## Session Management
74+
75+
**Storage priority:**
76+
77+
1. If `secondaryStorage` defined → sessions go there (not DB)
78+
2. Set `session.storeSessionInDatabase: true` to also persist to DB
79+
3. No database + `cookieCache` → fully stateless mode
80+
81+
**Cookie cache strategies:**
82+
83+
- `compact` (default) - Base64url + HMAC. Smallest.
84+
- `jwt` - Standard JWT. Readable but signed.
85+
- `jwe` - Encrypted. Maximum security.
86+
87+
**Key options:** `session.expiresIn` (default 7 days), `session.updateAge` (refresh interval), `session.cookieCache.maxAge`, `session.cookieCache.version` (change to invalidate all sessions).
88+
89+
---
90+
91+
## User & Account Config
92+
93+
**User:** `user.modelName`, `user.fields` (column mapping), `user.additionalFields`, `user.changeEmail.enabled` (disabled by default), `user.deleteUser.enabled` (disabled by default).
94+
95+
**Account:** `account.modelName`, `account.accountLinking.enabled`, `account.storeAccountCookie` (for stateless OAuth).
96+
97+
**Required for registration:** `email` and `name` fields.
98+
99+
---
100+
101+
## Email Flows
102+
103+
- `emailVerification.sendVerificationEmail` - Must be defined for verification to work
104+
- `emailVerification.sendOnSignUp` / `sendOnSignIn` - Auto-send triggers
105+
- `emailAndPassword.sendResetPassword` - Password reset email handler
106+
107+
---
108+
109+
## Security
110+
111+
**In `advanced`:**
112+
113+
- `useSecureCookies` - Force HTTPS cookies
114+
- `disableCSRFCheck` - ⚠️ Security risk
115+
- `disableOriginCheck` - ⚠️ Security risk
116+
- `crossSubDomainCookies.enabled` - Share cookies across subdomains
117+
- `ipAddress.ipAddressHeaders` - Custom IP headers for proxies
118+
- `database.generateId` - Custom ID generation or `"serial"`/`"uuid"`/`false`
119+
120+
**Rate limiting:** `rateLimit.enabled`, `rateLimit.window`, `rateLimit.max`, `rateLimit.storage` ("memory" | "database" | "secondary-storage").
121+
122+
---
123+
124+
## Hooks
125+
126+
**Endpoint hooks:** `hooks.before` / `hooks.after` - Array of `{ matcher, handler }`. Use `createAuthMiddleware`. Access `ctx.path`, `ctx.context.returned` (after), `ctx.context.session`.
127+
128+
**Database hooks:** `databaseHooks.user.create.before/after`, same for `session`, `account`. Useful for adding default values or post-creation actions.
129+
130+
**Hook context (`ctx.context`):** `session`, `secret`, `authCookies`, `password.hash()`/`verify()`, `adapter`, `internalAdapter`, `generateId()`, `tables`, `baseURL`.
131+
132+
---
133+
134+
## Plugins
135+
136+
**Import from dedicated paths for tree-shaking:**
137+
138+
```
139+
import { twoFactor } from "better-auth/plugins/two-factor"
140+
```
141+
142+
NOT `from "better-auth/plugins"`.
143+
144+
**Popular plugins:** `twoFactor`, `organization`, `passkey`, `magicLink`, `emailOtp`, `username`, `phoneNumber`, `admin`, `apiKey`, `bearer`, `jwt`, `multiSession`, `sso`, `oauthProvider`, `oidcProvider`, `openAPI`, `genericOAuth`.
145+
146+
Client plugins go in `createAuthClient({ plugins: [...] })`.
147+
148+
---
149+
150+
## Client
151+
152+
Import from: `better-auth/client` (vanilla), `better-auth/react`, `better-auth/vue`, `better-auth/svelte`, `better-auth/solid`.
153+
154+
Key methods: `signUp.email()`, `signIn.email()`, `signIn.social()`, `signOut()`, `useSession()`, `getSession()`, `revokeSession()`, `revokeSessions()`.
155+
156+
---
157+
158+
## Type Safety
159+
160+
Infer types: `typeof auth.$Infer.Session`, `typeof auth.$Infer.Session.user`.
161+
162+
For separate client/server projects: `createAuthClient<typeof auth>()`.
163+
164+
---
165+
166+
## Common Gotchas
167+
168+
1. **Model vs table name** - Config uses ORM model name, not DB table name
169+
2. **Plugin schema** - Re-run CLI after adding plugins
170+
3. **Secondary storage** - Sessions go there by default, not DB
171+
4. **Cookie cache** - Custom session fields NOT cached, always re-fetched
172+
5. **Stateless mode** - No DB = session in cookie only, logout on cache expiry
173+
6. **Change email flow** - Sends to current email first, then new email
174+
175+
---
176+
177+
## Resources
178+
179+
- [Docs](https://better-auth.com/docs)
180+
- [Options Reference](https://better-auth.com/docs/reference/options)
181+
- [LLMs.txt](https://better-auth.com/llms.txt)
182+
- [GitHub](https://github.com/better-auth/better-auth)
183+
- [Init Options Source](https://github.com/better-auth/better-auth/blob/main/packages/core/src/types/init-options.ts)

0 commit comments

Comments
 (0)