create-auth

작성자: better-auth

Better Auth를 사용하여 TypeScript/JavaScript 앱에서 인증을 스캐폴드하고 구현합니다. 프레임워크를 감지하고, 데이터베이스 어댑터를 구성하며, 라우트 핸들러를 설정합니다,…

npx skills add https://github.com/better-auth/skills --skill create-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.


Phase 1: Planning (REQUIRED before implementation)

Before writing any code, gather requirements by scanning the project and asking the user structured questions. This ensures the implementation matches their needs.

Step 1: Scan the project

Analyze the codebase to auto-detect:

  • Framework — Look for next.config, svelte.config, nuxt.config, astro.config, vite.config, or Express/Hono entry files.
  • Database/ORM — Look for prisma/schema.prisma, drizzle.config.ts, package.json deps (pg, postgres, @neondatabase/serverless, mysql2, better-sqlite3, mongoose, mongodb). If drizzle.config.ts exists, read its dialect field to determine the DB type (e.g., "postgresql" → Drizzle + Postgres). Also check which Drizzle driver is installed (drizzle-orm/node-postgrespg, drizzle-orm/postgres-jspostgres, drizzle-orm/neon-http → Neon).
  • Existing auth — Look for existing auth libraries (next-auth, lucia, clerk, supabase/auth, firebase/auth) in package.json or imports.
  • Package manager — Check for pnpm-lock.yaml, yarn.lock, bun.lockb, or package-lock.json.

Use what you find to pre-fill defaults and skip questions you can already answer.

Step 2: Ask planning questions

Use the AskQuestion tool to ask the user all applicable questions in a single call. Skip any question you already have a confident answer for from the scan. Group them under a title like "Auth Setup Planning".

Questions to ask:

  1. Project type (skip if detected)

    • Prompt: "What type of project is this?"
    • Options: New project from scratch | Adding auth to existing project | Migrating from another auth library
  2. Framework (skip if detected)

    • Prompt: "Which framework are you using?"
    • Options: Next.js (App Router) | Next.js (Pages Router) | SvelteKit | Nuxt | Astro | Express | Hono | SolidStart | Other
  3. Database & ORM (skip if detected)

    • Prompt: "Which database setup will you use?"
    • Options: PostgreSQL (Prisma) | PostgreSQL (Drizzle) | PostgreSQL (pg driver) | MySQL (Prisma) | MySQL (Drizzle) | MySQL (mysql2 driver) | SQLite (Prisma) | SQLite (Drizzle) | SQLite (better-sqlite3 driver) | MongoDB (Mongoose) | MongoDB (native driver)
  4. Authentication methods (always ask, allow multiple)

    • Prompt: "Which sign-in methods do you need?"
    • Options: Email & password | Social OAuth (Google, GitHub, etc.) | Magic link (passwordless email) | Passkey (WebAuthn) | Phone number
    • allow_multiple: true
  5. Social providers (only if they selected Social OAuth above — ask in a follow-up call)

    • Prompt: "Which social providers do you need?"
    • Options: Google | GitHub | Apple | Microsoft | Discord | Twitter/X
    • allow_multiple: true
  6. Email verification (only if Email & password was selected above — ask in a follow-up call)

    • Prompt: "Do you want to require email verification?"
    • Options: Yes | No
  7. Email provider (only if email verification is Yes, or if Password reset is selected in features — ask in a follow-up call)

    • Prompt: "How do you want to send emails?"
    • Options: Resend | Mock it for now (console.log)
  8. Features & plugins (always ask, allow multiple)

    • Prompt: "Which additional features do you need?"
    • Options: Two-factor authentication (2FA) | Organizations / teams | Admin dashboard | API bearer tokens | Password reset | None of these
    • allow_multiple: true
  9. Auth pages (always ask, allow multiple — pre-select based on earlier answers)

    • Prompt: "Which auth pages do you need?"
    • Options vary based on previous answers:
      • Always available: Sign in | Sign up
      • If Email & password selected: Forgot password | Reset password
      • If email verification enabled: Email verification
    • allow_multiple: true
  10. Auth UI style (always ask)

  • Prompt: "What style do you want for the auth pages? Pick one or describe your own."
  • Options: Minimal & clean | Centered card with background | Split layout (form + hero image) | Floating / glassmorphism | Other (I'll describe)

Step 3: Summarize the plan

After collecting answers, present a concise implementation plan as a markdown checklist. Example:

## Auth Implementation Plan

- **Framework:** Next.js (App Router)
- **Database:** PostgreSQL via Prisma
- **Auth methods:** Email/password, Google OAuth, GitHub OAuth
- **Plugins:** 2FA, Organizations, Email verification
- **UI:** Custom forms

### Steps
1. Install `better-auth` and `@better-auth/cli`
2. Create `lib/auth.ts` with server config
3. Create `lib/auth-client.ts` with React client
4. Set up route handler at `app/api/auth/[...all]/route.ts`
5. Configure Prisma adapter and generate schema
6. Add Google & GitHub OAuth providers
7. Enable `twoFactor` and `organization` plugins
8. Set up email verification handler
9. Run migrations
10. Create sign-in / sign-up pages

Ask the user to confirm the plan before proceeding to Phase 2.


Phase 2: Implementation

Only proceed here after the user confirms the plan from Phase 1.

Follow the decision tree below, guided by the answers collected above.

Is this a new/empty project?
├─ YES → New project setup
│   1. Install better-auth (+ scoped packages per plan)
│   2. Create auth.ts with all planned config
│   3. Create auth-client.ts with framework client
│   4. Set up route handler
│   5. Set up environment variables
│   6. Run CLI migrate/generate
│   7. Add plugins from plan
│   8. Create auth UI pages
│
├─ MIGRATING → Migration from existing auth
│   1. Audit current auth for gaps
│   2. Plan incremental migration
│   3. Install better-auth alongside existing auth
│   4. Migrate routes, then session logic, then UI
│   5. Remove old auth library
│   6. See migration guides in docs
│
└─ ADDING → Add auth to existing project
    1. Analyze project structure
    2. Install better-auth
    3. Create auth config matching plan
    4. Add route handler
    5. Run schema migrations
    6. Integrate into existing pages
    7. Add planned plugins and features

At the end of implementation, guide users thoroughly on remaining next steps (e.g., setting up OAuth app credentials, deploying env vars, testing flows).


Installation

Core: npm install better-auth

Scoped packages (as needed):

PackageUse case
@better-auth/passkeyWebAuthn/Passkey auth
@better-auth/ssoSAML/OIDC enterprise SSO
@better-auth/stripeStripe payments
@better-auth/scimSCIM user provisioning
@better-auth/expoReact 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:

FrameworkImport
React/Next.jsbetter-auth/react
Vuebetter-auth/vue
Sveltebetter-auth/svelte
Solidbetter-auth/solid
Vanilla JSbetter-auth/client

Client plugins go in createAuthClient({ plugins: [...] }).

Common exports: signIn, signUp, signOut, useSession, getSession


Route Handler Setup

FrameworkFileHandler
Next.js App Routerapp/api/auth/[...all]/route.tstoNextJsHandler(auth) → export { GET, POST }
Next.js Pagespages/api/auth/[...all].tstoNextJsHandler(auth) → default export
ExpressAny fileapp.all("/api/auth/*", toNodeHandler(auth))
SvelteKitsrc/hooks.server.tssvelteKitHandler(auth)
SolidStartRoute filesolidStartHandler(auth)
HonoRoute fileauth.handler(c.req.raw)

Next.js Server Components: Add nextCookies() plugin to auth config.


Database Migrations

AdapterCommand
Built-in Kyselynpx @better-auth/cli@latest migrate (applies directly)
Prismanpx @better-auth/cli@latest generate --output prisma/schema.prisma then npx prisma migrate dev
Drizzle (dev)npx @better-auth/cli@latest generate --output src/db/auth-schema.ts then npx drizzle-kit push
Drizzle (prod)npx @better-auth/cli@latest generate --output src/db/auth-schema.ts then npx drizzle-kit generate then npx drizzle-kit migrate

Note: drizzle-kit push skips migration files and is only safe for development. Use drizzle-kit generate + drizzle-kit migrate in production.

Re-run after adding plugins.


Database Adapters

DatabaseSetup
SQLitePass better-sqlite3 or bun:sqlite instance directly
PostgreSQLPass pg.Pool instance directly
MySQLPass mysql2 pool directly
PrismaprismaAdapter(prisma, { provider: "postgresql" }) from better-auth/adapters/prisma
Drizzle (pg)drizzleAdapter(db, { provider: "pg" }) from better-auth/adapters/drizzle
Drizzle (mysql)drizzleAdapter(db, { provider: "mysql" }) from better-auth/adapters/drizzle
Drizzle (sqlite)drizzleAdapter(db, { provider: "sqlite" }) from better-auth/adapters/drizzle
MongoDBmongodbAdapter(db) from better-auth/adapters/mongodb

Drizzle + PostgreSQL Setup

Before using drizzleAdapter, initialize the db instance:

// Option 1: node-postgres (pg)
import { drizzle } from "drizzle-orm/node-postgres"
import { Pool } from "pg"
import * as schema from "./auth-schema"

const pool = new Pool({ connectionString: process.env.DATABASE_URL })
export const db = drizzle(pool, { schema })
// Option 2: postgres.js
import { drizzle } from "drizzle-orm/postgres-js"
import postgres from "postgres"
import * as schema from "./auth-schema"

const client = postgres(process.env.DATABASE_URL!)
export const db = drizzle(client, { schema })
// Option 3: Neon serverless
import { drizzle } from "drizzle-orm/neon-http"
import { neon } from "@neondatabase/serverless"
import * as schema from "./auth-schema"

const sql = neon(process.env.DATABASE_URL!)
export const db = drizzle(sql, { schema })

Then pass to Better Auth:

import { betterAuth } from "better-auth"
import { drizzleAdapter } from "better-auth/adapters/drizzle"
import { db } from "./db"

export const auth = betterAuth({
  database: drizzleAdapter(db, { provider: "pg" }),
  // ...
})

Drizzle Config (drizzle.config.ts)

Required for drizzle-kit commands to find your schema:

import { defineConfig } from "drizzle-kit"

export default defineConfig({
  schema: "./src/db/auth-schema.ts",
  out: "./drizzle",
  dialect: "postgresql",
  dbCredentials: {
    url: process.env.DATABASE_URL!,
  },
})

Common Plugins

PluginServer ImportClient ImportPurpose
twoFactorbetter-auth/pluginstwoFactorClient2FA with TOTP/OTP
organizationbetter-auth/pluginsorganizationClientTeams/orgs
adminbetter-auth/pluginsadminClientUser management
bearerbetter-auth/plugins-API token auth
openAPIbetter-auth/plugins-API docs
passkey@better-auth/passkeypasskeyClientWebAuthn
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_SECRET set (32+ chars)
  • advanced.useSecureCookies: true in production
  • trustedOrigins configured
  • Rate limits enabled
  • Email verification enabled
  • Password reset implemented
  • 2FA for sensitive apps
  • CSRF protection NOT disabled
  • account.accountLinking reviewed

Troubleshooting

IssueFix
"Secret not set"Add BETTER_AUTH_SECRET env var
"Invalid Origin"Add domain to trustedOrigins
Cookies not settingCheck baseURL matches domain; enable secure cookies in prod
OAuth callback errorsVerify redirect URIs in provider dashboard
Type errors after adding pluginRe-run CLI generate/migrate

Resources

better-auth의 다른 스킬

better-auth-best-practices
better-auth
완전한 Better Auth 서버 및 클라이언트 설정으로, 데이터베이스 어댑터, 세션 관리, 플러그인, 보안 구성을 포함합니다. 설치부터 데이터베이스 마이그레이션, 환경 변수 설정, 여러 프레임워크에서의 라우트 핸들러 생성까지 전체 워크플로우를 다룹니다. 여러 데이터베이스 어댑터(Prisma, Drizzle, MongoDB, 직접 연결)를 지원하며, 모델과 테이블 명명 규칙에 대한 중요한 지침을 제공합니다. 세션 저장소 전략(Redis/KV를 사용한 보조 저장소), 쿠키...
official
better-auth-security-best-practices
better-auth
속도 제한 구성, 인증 비밀 관리, CSRF 보호 설정, 신뢰할 수 있는 출처 정의, 세션 및 쿠키 보안, OAuth 토큰 암호화, IP 추적…
official
Email & Password Best Practices
better-auth
이메일 및 비밀번호 모범 사례 — AI 에이전트용 설치 가능한 스킬, better-auth/skills에서 게시함.
official
email-and-password-best-practices
better-auth
이메일 인증, 비밀번호 재설정 흐름, 그리고 Better Auth를 위한 사용자 정의 가능한 비밀번호 정책을 제공합니다. 선택적 강제 적용을 통해 인증될 때까지 로그인을 차단하는 이메일 인증을 지원하며, 구성 가능한 토큰 만료 및 일회용 재설정 토큰을 포함합니다. 내장된 보안 기능을 갖춘 비밀번호 재설정 흐름: 백그라운드 이메일 전송, 타이밍 공격 방지, 유효하지 않은 요청에 대한 더미 작업, 재설정 시 선택적 세션 취소를 제공합니다. 구성 가능한 비밀번호 길이 제한(기본 8~256자) 및 사용자 정의...
official
organization-best-practices
better-auth
멀티 테넌트 조직 설정: 멤버 관리, 역할 기반 접근 제어, Better Auth를 통한 팀 지원. 사용자 정의 가능한 생성 규칙, 멤버십 제한, 소유권 제약 조건으로 조직을 구성하며, 생성자는 자동으로 소유자 역할을 부여받습니다. 이메일 전송, 만료 기간, 공유 가능한 초대 URL을 통해 멤버와 초대를 관리하고, 멤버당 여러 역할을 지원합니다. 동적 접근 제어로 사용자 정의 역할과 권한을 정의하고, 권한을 확인합니다...
official
two-factor-authentication-best-practices
better-auth
Better Auth를 위한 TOTP, OTP, 백업 코드 및 신뢰 기기 관리를 포함한 다중 인증. 세 가지 인증 방식을 지원합니다: 인증 앱(QR 코드를 통한 TOTP), 이메일/SMS 코드(OTP), 일회용 백업 코드. 자동 세션 관리, 임시 2FA 쿠키, 만료 설정이 가능한 신뢰 기기 추적을 포함한 완전한 2FA 로그인 흐름을 처리합니다. 속도 제한(10초당 3회 요청), 저장 시 암호화 등 내장 보안 기능을 제공합니다...
official
create-auth-skill
better-auth
TypeScript/JavaScript 앱에서 Better Auth 프레임워크 감지, 데이터베이스 어댑터 설정, OAuth 통합을 통해 인증을 스캐폴딩하고 구현합니다. 프로젝트 스캐닝을 통해 프레임워크(Next.js, SvelteKit, Nuxt, Astro, Express, Hono), 데이터베이스(Prisma, Drizzle, MongoDB, raw 드라이버), 기존 인증 라이브러리를 감지합니다. 이메일/비밀번호, OAuth(Google, GitHub, Apple, Microsoft, Discord, Twitter), 매직 링크, 패스키, 전화 인증을 지원하며 설정 가능한 이메일 확인 기능을 제공합니다...
official
agent-auth-cli
better-auth
Agent Auth CLI(auth-agent)를 사용하여 제공자를 검색하고, 에이전트를 연결하며, 기능을 관리하고, 작업을 실행하세요. 사용자가 상호작용을 원할 때 사용합니다…
official