better-auth
Self-hosted TypeScript auth framework with social auth, 2FA, passkeys, organizations, RBAC, and 15+ plugins. Supports Drizzle/Prisma/Kysely adapters. Self-hosted alternative to Clerk/Auth.js. Use when: configuring auth, adding plugins, social OAuth, multi-tenant SaaS, organizations with teams and RBAC, two-factor authentication (TOTP/OTP/backup codes), email verification, password reset flows, session management, rate limiting, CSRF and cookie security, Expo/mobile, D1 adapter errors, TanStack Start integration, additionalFields bugs, admin plugin, migrating from NextAuth, migrating from Clerk, migrating from Supabase Auth, or troubleshooting auth issues.
How do I install this agent skill?
npx skills add https://github.com/oakoss/agent-skills --skill better-authIs this agent skill safe to install?
- Gen Agent Trust Hubpass
This skill provides comprehensive documentation and configuration guidance for Better Auth, a TypeScript authentication framework. It covers setup, database adapters, plugins (2FA, organizations, etc.), and security best practices like CSRF protection and rate limiting. No malicious patterns, obfuscation, or unauthorized access attempts were identified.
- Socketpass
No alerts
- Snykpass
Risk: LOW · No issues
- Runlayerwarn
10/11 files flagged
What does this agent skill do?
better-auth
Package: better-auth@1.4.15 (ESM-only since v1.4.0) Docs: https://better-auth.com/docs | GitHub: https://github.com/better-auth/better-auth
Environment Setup
| Variable | Purpose |
|---|---|
BETTER_AUTH_SECRET | Encryption secret (min 32 chars). Generate: openssl rand -base64 32 |
BETTER_AUTH_URL | Base URL (e.g., https://example.com) |
Only define baseURL/secret in config if env vars are NOT set. CLI looks for auth.ts in: ./, ./lib, ./utils, or ./src.
Core Config Options
| Option | Notes |
|---|---|
appName | Optional display name |
baseURL | Only if BETTER_AUTH_URL not set |
basePath | Default /api/auth. Set / for root. |
secret | Only if BETTER_AUTH_SECRET not set |
database | Required unless using stateless mode (v1.4+) |
secondaryStorage | Redis/KV for sessions and rate limits |
emailAndPassword | { enabled: true } to activate |
socialProviders | { google: { clientId, clientSecret }, ... } |
plugins | Array of plugins |
trustedOrigins | CSRF whitelist |
Plugin Reference
| Plugin | Description |
|---|---|
| twoFactor | TOTP, email OTP, backup codes |
| organization | Multi-tenant orgs, teams, invitations, RBAC |
| admin | User management, impersonation, banning |
| passkey | WebAuthn passwordless login |
| magicLink | Email-based passwordless login |
| jwt | JWT tokens with key rotation, JWKS |
| oauthProvider | Build your own OAuth 2.1 provider (separate @better-auth/oauth-provider package) |
| sso | Enterprise SSO with OIDC, OAuth2, SAML 2.0 (separate @better-auth/sso package) |
| scim | Enterprise user provisioning (separate @better-auth/scim package) |
| stripe | Payment and subscription management |
| bearer | API token auth for mobile/CLI |
| apiKey | Token-based auth with rate limits |
| oneTap | Google One Tap frictionless sign-in |
| anonymous | Guest user access without PII |
| genericOAuth | Custom OAuth providers with PKCE |
| emailOTP | Email-based one-time password auth |
| phoneNumber | Phone/SMS-based OTP sign-in |
| username | Username-based sign-in (alternative to email) |
| multiSession | Multiple accounts in same browser |
| openAPI | Interactive API docs at /api/auth/reference |
Session Strategies
| Strategy | Format | Use Case |
|---|---|---|
| Compact (default) | Base64url + HMAC-SHA256 | Smallest, fastest |
| JWT | Standard JWT | Interoperable |
| JWE | A256CBC-HS512 encrypted | Most secure |
Getting Started
For new projects or first-time Better Auth setup, use the official interactive setup skill:
npx skills add better-auth/skills -s create-auth-skill
This walks through framework detection, database selection, auth method choices, plugin setup, and generates the initial configuration.
Anti-Patterns
| Anti-Pattern | Correct Approach |
|---|---|
Using d1Adapter | Use Drizzle or Kysely adapter with provider: "sqlite" |
| Using table name in config | Use ORM model name, not DB table name |
| Forgetting CLI after plugin changes | Re-run npx @better-auth/cli@latest generate |
tanstackStartCookies() not last plugin | Must be the last plugin in array (TanStack Start) |
Checking session for login state | Check session?.user — session object is always truthy |
Missing nodejs_compat flag | Required in wrangler.toml for Cloudflare Workers |
| Kysely CamelCasePlugin with auth | Use separate Kysely instance without the plugin |
Using old reactStartCookies import | Renamed to tanstackStartCookies from better-auth/tanstack-start in v1.4.14 |
Common Mistakes
| Mistake | Correct Pattern |
|---|---|
Setting baseURL and secret in config when env vars are already set | Only define these in config if BETTER_AUTH_URL and BETTER_AUTH_SECRET env vars are NOT set |
| Using CommonJS require syntax with better-auth v1.4+ | better-auth is ESM-only since v1.4.0; use import syntax exclusively |
| Not re-running CLI generate after adding or changing plugins | Always run npx @better-auth/cli@latest generate after plugin changes to update DB schema |
Checking session object truthy state for login detection | Check session?.user instead; the session object itself is always truthy |
Using d1Adapter directly for Cloudflare D1 | Use Drizzle or Kysely adapter with provider: "sqlite" for D1 compatibility |
Breaking Changes
| Version | Change |
|---|---|
| v1.4.14 | reactStartCookies renamed to tanstackStartCookies (import from better-auth/tanstack-start) |
| v1.4.6 | allowImpersonatingAdmins defaults to false |
| v1.4.0 | ESM-only (no CommonJS); SSO, SCIM, OAuth Provider moved to separate packages |
| v1.3.0 | Multi-team table structure: new teamMembers table needed |
Delegation
When working on auth, delegate to:
application-security— Security architecture and threat modelingdatabase— Drizzle ORM schema and migrationstanstack-start— TanStack Start integration patterns
Resources
- Docs: https://better-auth.com/docs
- Options Reference: https://better-auth.com/docs/reference/options
- LLMs.txt: https://better-auth.com/llms.txt
- Changelog: https://www.better-auth.com/changelogs
- TanStack Start: https://www.better-auth.com/docs/integrations/tanstack
- Expo: https://www.better-auth.com/docs/integrations/expo
References
- Database Adapters — Drizzle, Kysely, Prisma adapters, Cloudflare Workers factory pattern
- Session Management — Cookie cache, stateless sessions, storage priority, freshAge constraints
- Plugins and Social Auth — Plugin setup, OAuth 2.1 provider, admin RBAC, social provider scopes
- Email and Password — Verification, password reset, timing attack prevention, hashing (scrypt, argon2), token security
- Two-Factor Authentication — TOTP, email/SMS OTP, backup codes, trusted devices, 2FA session flow
- Organizations — Multi-tenant orgs, teams, invitations, RBAC, dynamic access control, lifecycle hooks
- Configuration — User/account config, rate limiting, hooks, CSRF, trusted origins, cookie/OAuth security, production checklist
- Framework Integration — TanStack Start setup, Expo/React Native, client imports, type safety
- Migration Guides — Migrate from NextAuth/Auth.js, Clerk, or Supabase Auth with schema mappings and session strategies
- Troubleshooting — D1 consistency, CORS, OAuth redirect, admin 403, nanostore refresh, known bugs
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/oakoss/agent-skills/better-auth">View better-auth on skillZs</a>