Security audit workflow - vulnerability scan β verification
npx skills add better-auth/skills --skill "create-auth-skill"
Install specific skill from multi-skill repository
# Description
Skill for creating auth layers in TypeScript/JavaScript apps using Better Auth.
# SKILL.md
name: create-auth-skill
description: Skill for creating auth layers in TypeScript/JavaScript apps using Better Auth.
Create Auth Skill
Guide for adding authentication to TypeScript/JavaScript applications using Better Auth.
For code examples and syntax, see better-auth.com/docs.
Decision Tree
Is this a new/empty project?
ββ YES β New project setup
β 1. Identify framework
β 2. Choose database
β 3. Install better-auth
β 4. Create auth.ts + auth-client.ts
β 5. Set up route handler
β 6. Run CLI migrate/generate
β 7. Add features via plugins
β
ββ NO β Does project have existing auth?
ββ YES β Migration/enhancement
β β’ Audit current auth for gaps
β β’ Plan incremental migration
β β’ See migration guides in docs
β
ββ NO β Add auth to existing project
1. Analyze project structure
2. Install better-auth
3. Create auth config
4. Add route handler
5. Run schema migrations
6. Integrate into existing pages
Installation
Core: npm install better-auth
Scoped packages (as needed):
| Package | Use case |
|---------|----------|
| @better-auth/passkey | WebAuthn/Passkey auth |
| @better-auth/sso | SAML/OIDC enterprise SSO |
| @better-auth/stripe | Stripe payments |
| @better-auth/scim | SCIM user provisioning |
| @better-auth/expo | React Native/Expo |
Environment Variables
BETTER_AUTH_SECRET=<32+ chars, generate with: openssl rand -base64 32>
BETTER_AUTH_URL=http://localhost:3000
DATABASE_URL=<your database connection string>
Add OAuth secrets as needed: GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, GOOGLE_CLIENT_ID, etc.
Server Config (auth.ts)
Location: lib/auth.ts or src/lib/auth.ts
Minimal config needs:
- database - Connection or adapter
- emailAndPassword: { enabled: true } - For email/password auth
Standard config adds:
- socialProviders - OAuth providers (google, github, etc.)
- emailVerification.sendVerificationEmail - Email verification handler
- emailAndPassword.sendResetPassword - Password reset handler
Full config adds:
- plugins - Array of feature plugins
- session - Expiry, cookie cache settings
- account.accountLinking - Multi-provider linking
- rateLimit - Rate limiting config
Export types: export type Session = typeof auth.$Infer.Session
Client Config (auth-client.ts)
Import by framework:
| Framework | Import |
|-----------|--------|
| React/Next.js | better-auth/react |
| Vue | better-auth/vue |
| Svelte | better-auth/svelte |
| Solid | better-auth/solid |
| Vanilla JS | better-auth/client |
Client plugins go in createAuthClient({ plugins: [...] }).
Common exports: signIn, signUp, signOut, useSession, getSession
Route Handler Setup
| Framework | File | Handler |
|---|---|---|
| Next.js App Router | app/api/auth/[...all]/route.ts |
toNextJsHandler(auth) β export { GET, POST } |
| Next.js Pages | pages/api/auth/[...all].ts |
toNextJsHandler(auth) β default export |
| Express | Any file | app.all("/api/auth/*", toNodeHandler(auth)) |
| SvelteKit | src/hooks.server.ts |
svelteKitHandler(auth) |
| SolidStart | Route file | solidStartHandler(auth) |
| Hono | Route file | auth.handler(c.req.raw) |
Next.js Server Components: Add nextCookies() plugin to auth config.
Database Migrations
| Adapter | Command |
|---|---|
| Built-in Kysely | npx @better-auth/cli@latest migrate (applies directly) |
| Prisma | npx @better-auth/cli@latest generate --output prisma/schema.prisma then npx prisma migrate dev |
| Drizzle | npx @better-auth/cli@latest generate --output src/db/auth-schema.ts then npx drizzle-kit push |
Re-run after adding plugins.
Database Adapters
| Database | Setup |
|---|---|
| SQLite | Pass better-sqlite3 or bun:sqlite instance directly |
| PostgreSQL | Pass pg.Pool instance directly |
| MySQL | Pass mysql2 pool directly |
| Prisma | prismaAdapter(prisma, { provider: "postgresql" }) from better-auth/adapters/prisma |
| Drizzle | drizzleAdapter(db, { provider: "pg" }) from better-auth/adapters/drizzle |
| MongoDB | mongodbAdapter(db) from better-auth/adapters/mongodb |
Common Plugins
| Plugin | Server Import | Client Import | Purpose |
|---|---|---|---|
twoFactor |
better-auth/plugins |
twoFactorClient |
2FA with TOTP/OTP |
organization |
better-auth/plugins |
organizationClient |
Teams/orgs |
admin |
better-auth/plugins |
adminClient |
User management |
bearer |
better-auth/plugins |
- | API token auth |
openAPI |
better-auth/plugins |
- | API docs |
passkey |
@better-auth/passkey |
passkeyClient |
WebAuthn |
sso |
@better-auth/sso |
- | Enterprise SSO |
Plugin pattern: Server plugin + client plugin + run migrations.
Auth UI Implementation
Sign in flow:
1. signIn.email({ email, password }) or signIn.social({ provider, callbackURL })
2. Handle error in response
3. Redirect on success
Session check (client): useSession() hook returns { data: session, isPending }
Session check (server): auth.api.getSession({ headers: await headers() })
Protected routes: Check session, redirect to /sign-in if null.
Security Checklist
- [ ]
BETTER_AUTH_SECRETset (32+ chars) - [ ]
advanced.useSecureCookies: truein production - [ ]
trustedOriginsconfigured - [ ] Rate limits enabled
- [ ] Email verification enabled
- [ ] Password reset implemented
- [ ] 2FA for sensitive apps
- [ ] CSRF protection NOT disabled
- [ ]
account.accountLinkingreviewed
Troubleshooting
| Issue | Fix |
|---|---|
| "Secret not set" | Add BETTER_AUTH_SECRET env var |
| "Invalid Origin" | Add domain to trustedOrigins |
| Cookies not setting | Check baseURL matches domain; enable secure cookies in prod |
| OAuth callback errors | Verify redirect URIs in provider dashboard |
| Type errors after adding plugin | Re-run CLI generate/migrate |
Resources
# Supported AI Coding Agents
This skill is compatible with the SKILL.md standard and works with all major AI coding agents:
Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.