create-auth について
create-auth は、TypeScript/JavaScript アプリに Better Auth を導入するためのスキルです。実装前にプロジェクト構成と要件を確認し、設定、マイグレーション、認証 UI、安全性の確認を案内します。
主な機能
- 01フレームワーク・DB・既存認証の確認
- 02質問による要件収集
- 03Better Auth の設定案内
- 04クライアントとルートハンドラーの設定
- 05マイグレーションと安全性の確認
活用シーン
- 01既存アプリへの認証機能の追加
- 02サインイン方式と認証ページの計画
- 03DB アダプターとマイグレーションの設定
- 04認証実装のセキュリティ設定の点検
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ better-auth/ skills --skill create-authインストール後、Claude Code で/create-authを入力して読み込まれたか確認します。
詳細
認証スキルの作成
Better Auth を使用して、TypeScript/JavaScript アプリケーションに認証を追加するためのガイドです。
コード例と構文については、better-auth.com/docs を参照してください。
フェーズ 1:計画(実装前に必須)
コードを書く前に、プロジェクトを調査し、構造化された質問をユーザーに行って要件を収集します。これにより、ニーズに合った実装が可能になります。
ステップ 1:プロジェクトを調査する
コードベースを分析し、以下を自動検出します。
- フレームワーク —
next.config、svelte.config、nuxt.config、astro.config、vite.config、または Express/Hono のエントリーファイルを探します。 - データベース/ORM —
prisma/schema.prisma、drizzle.config.ts、package.jsonの依存関係(pg、postgres、@neondatabase/serverless、mysql2、better-sqlite3、mongoose、mongodb)を探します。drizzle.config.tsがある場合は、dialectフィールドを読み取り、データベースの種類を特定します(例:"postgresql"→ Drizzle + Postgres)。また、インストール済みの Drizzle ドライバーも確認します(drizzle-orm/node-postgres→pg、drizzle-orm/postgres-js→postgres、drizzle-orm/neon-http→ Neon)。 - 既存の認証 —
package.jsonまたはインポート内で、既存の認証ライブラリ(next-auth、lucia、clerk、supabase/auth、firebase/auth)を探します。 - パッケージマネージャー —
pnpm-lock.yaml、yarn.lock、bun.lockb、またはpackage-lock.jsonを確認します。
調査結果をもとにデフォルト値を事前入力し、すでに回答がわかっている質問は省略します。
ステップ 2:プランニングに関する質問をする
AskQuestion ツールを使って、該当するすべての質問を1 回の呼び出しでユーザーに尋ねます。スキャン結果からすでに確実な回答が得られている質問は省略します。「認証設定のプランニング」のようなタイトルの下に質問をまとめます。
質問する項目:
-
プロジェクトの種類(検出済みの場合は省略)
- プロンプト:「これはどの種類のプロジェクトですか?」
- 選択肢:ゼロから新しいプロジェクトを作成 | 既存のプロジェクトに認証を追加 | 別の認証ライブラリから移行
-
フレームワーク(検出済みの場合は省略)
- プロンプト:「使用しているフレームワークはどれですか?」
- 選択肢:Next.js (App Router) | Next.js (Pages Router) | SvelteKit | Nuxt | Astro | Express | Hono | SolidStart | その他
-
データベースと ORM(検出済みの場合は省略)
- プロンプト:「使用するデータベース構成はどれですか?」
- 選択肢: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)
-
認証方法(必ず尋ね、複数選択を許可)
- プロンプト:「必要なサインイン方法はどれですか?」
- 選択肢:メールアドレスとパスワード | ソーシャル OAuth(Google、GitHub など) | マジックリンク(パスワード不要のメール認証) | パスキー(WebAuthn) | 電話番号
allow_multiple: true
-
ソーシャルプロバイダー(上記でソーシャル OAuth を選択した場合のみ、後続の呼び出しで尋ねる)
- プロンプト:「必要なソーシャルプロバイダーはどれですか?」
- 選択肢:Google | GitHub | Apple | Microsoft | Discord | Twitter/X
allow_multiple: true
-
メールアドレスの確認(上記でメールアドレスとパスワードを選択した場合のみ、後続の呼び出しで尋ねる)
- プロンプト:「メールアドレスの確認を必須にしますか?」
- 選択肢:はい | いいえ
-
メールプロバイダー(メールアドレスの確認が「はい」の場合、または機能でパスワードリセットを選択した場合のみ、後続の呼び出しで尋ねる)
- プロンプト:「メールをどのように送信しますか?」
- 選択肢:Resend | 今はモックにする(console.log)
-
機能とプラグイン(必ず尋ね、複数選択を許可)
- プロンプト:「追加で必要な機能はどれですか?」
- 選択肢:二要素認証(2FA) | 組織/チーム | 管理者ダッシュボード | API ベアラートークン | パスワードリセット | 該当なし
allow_multiple: true
-
認証ページ(必ず尋ね、複数選択を許可。前の回答に基づいて事前選択する)
- プロンプト:「必要な認証ページはどれですか?」
- 選択肢は前の回答に応じて変わります:
- 常に選択可能:サインイン | サインアップ
- メールアドレスとパスワードを選択した場合:パスワードを忘れた場合 | パスワードのリセット
- メールアドレスの確認を有効にした場合:メールアドレスの確認
allow_multiple: true
-
認証 UI のスタイル(必ず尋ねる)
- プロンプト:「認証ページのスタイルはどれがよいですか?1 つ選ぶか、独自のスタイルを説明してください。」
- 選択肢:ミニマルでシンプル | 背景付きの中央配置カード | 分割レイアウト(フォーム+ヒーロー画像) | フローティング/グラスモーフィズム | その他(説明してください)
ステップ 3:プランをまとめる
回答を集めたら、Markdown のチェックリストで実装プランを簡潔に提示します。例:
## 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` (the CLI ships as the `auth` package and is run via `npx auth@latest`, no install needed)
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
フェーズ 2 に進む前に、プランを確認するようユーザーに依頼します。
フェーズ 2:実装
フェーズ 1 のプランをユーザーが確認した後にのみ、ここに進みます。
以下の判断ツリーに従い、上記で集めた回答を参考にします。
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
実装の最後に、残りの次のステップ(OAuth アプリの認証情報の設定、環境変数のデプロイ、認証フローのテストなど)について、ユーザーに十分に案内します。
インストール
コア: npm install better-auth
スコープ付きパッケージ(必要に応じて):
| パッケージ | 用途 |
|---|---|
@better-auth/passkey | WebAuthn/パスキー認証 |
@better-auth/sso | SAML/OIDC エンタープライズ SSO |
@better-auth/stripe | Stripe 決済 |
@better-auth/scim | SCIM ユーザープロビジョニング |
@better-auth/expo | React Native/Expo |
環境変数
BETTER_AUTH_SECRET=<32+ chars, generate with: openssl rand -base64 32>
BETTER_AUTH_URL=http://localhost:3000
DATABASE_URL=<your database connection string>
必要に応じて OAuth シークレットを追加します:GITHUB_CLIENT_ID、GITHUB_CLIENT_SECRET、GOOGLE_CLIENT_ID など。
サーバー設定(auth.ts)
場所: lib/auth.ts または src/lib/auth.ts
最小限の設定に必要な項目:
database- 接続またはアダプターemailAndPassword: { enabled: true }- メールアドレスとパスワードによる認証用
標準設定で追加する項目:
socialProviders- OAuth プロバイダー(google、github など)emailVerification.sendVerificationEmail- メール認証ハンドラーemailAndPassword.sendResetPassword- パスワードリセットハンドラー
完全な設定で追加する項目:
plugins- 機能プラグインの配列session- 有効期限、Cookie キャッシュ設定account.accountLinking- 複数プロバイダーの連携rateLimit- レート制限の設定
型をエクスポート: export type Session = typeof auth.$Infer.Session
クライアント設定(auth-client.ts)
フレームワーク別のインポート:
| フレームワーク | インポート |
|---|---|
| React/Next.js | better-auth/react |
| Vue | better-auth/vue |
| Svelte | better-auth/svelte |
| Solid | better-auth/solid |
| Vanilla JS | better-auth/client |
クライアントプラグインは createAuthClient({ plugins: [...] }) に記述します。
一般的なエクスポート: signIn、signUp、signOut、useSession、getSession
ルートハンドラーの設定
| フレームワーク | ファイル | ハンドラー |
|---|---|---|
| Next.js App Router | app/api/auth/[...all]/route.ts | toNextJsHandler(auth) → { GET, POST } をエクスポート |
| Next.js Pages | pages/api/auth/[...all].ts | toNextJsHandler(auth) → デフォルトエクスポート |
| Express | 任意のファイル | app.all("/api/auth/*", toNodeHandler(auth)) |
| SvelteKit | src/hooks.server.ts | svelteKitHandler(auth) |
| SolidStart | ルートファイル | solidStartHandler(auth) |
| Hono | ルートファイル | auth.handler(c.req.raw) |
Next.js Server Components: nextCookies() プラグインを auth 設定に追加します。
データベースのマイグレーション
| アダプター | コマンド |
|---|---|
| 組み込みの Kysely | npx auth@latest migrate(直接適用) |
| Prisma | npx auth@latest generate --output prisma/schema.prisma の後に npx prisma migrate dev |
| Drizzle(開発環境) | npx auth@latest generate --output src/db/auth-schema.ts の後に npx drizzle-kit push |
| Drizzle(本番環境) | npx auth@latest generate --output src/db/auth-schema.ts の後に npx drizzle-kit generate、続けて npx drizzle-kit migrate |
注:
drizzle-kit pushはマイグレーションファイルを作成せず、開発環境でのみ安全に使用できます。本番環境ではdrizzle-kit generateとdrizzle-kit migrateを使用してください。
プラグインを追加した後は、再実行してください。
データベースアダプター
| データベース | 設定 |
|---|---|
| SQLite | better-sqlite3 または bun:sqlite のインスタンスを直接渡します |
| PostgreSQL | pg.Pool のインスタンスを直接渡します |
| MySQL | mysql2 のプールを直接渡します |
| Prisma | better-auth/adapters/prisma の prismaAdapter(prisma, { provider: "postgresql" }) |
| Drizzle(pg) | better-auth/adapters/drizzle の drizzleAdapter(db, { provider: "pg" }) |
| Drizzle(mysql) | better-auth/adapters/drizzle の drizzleAdapter(db, { provider: "mysql" }) |
| Drizzle(sqlite) | better-auth/adapters/drizzle の drizzleAdapter(db, { provider: "sqlite" }) |
| MongoDB | better-auth/adapters/mongodb の mongodbAdapter(db) |
Drizzle + PostgreSQL の設定
drizzleAdapter を使用する前に、db インスタンスを初期化します。
// 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 })
次に 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 の設定(drizzle.config.ts)
drizzle-kit コマンドでスキーマを参照するために必要です。
import { defineConfig } from "drizzle-kit"
export default defineConfig({
schema: "./src/db/auth-schema.ts",
out: "./drizzle",
dialect: "postgresql",
dbCredentials: {
url: process.env.DATABASE_URL!,
},
})
一般的なプラグイン
| プラグイン | サーバーのインポート | クライアントのインポート | 用途 |
|---|---|---|---|
twoFactor | better-auth/plugins | twoFactorClient | TOTP/OTP による 2 要素認証 |
organization | better-auth/plugins | organizationClient | チーム/組織 |
admin | better-auth/plugins | adminClient | ユーザー管理 |
bearer | better-auth/plugins | - | API トークン認証 |
openAPI | better-auth/plugins | - | API ドキュメント |
passkey | @better-auth/passkey | passkeyClient | WebAuthn |
sso | @better-auth/sso | - | エンタープライズ SSO |
プラグインのパターン: サーバープラグインとクライアントプラグインを追加し、マイグレーションを実行します。
認証 UI の実装
サインインのフロー:
signIn.email({ email, password })またはsignIn.social({ provider, callbackURL })を実行します- レスポンスの
errorを処理します - 成功したらリダイレクトします
セッションの確認(クライアント): useSession() フックは { data: session, isPending } を返します
セッションの確認(サーバー): auth.api.getSession({ headers: await headers() })
保護されたルート: セッションを確認し、null の場合は /sign-in にリダイレクトします。
セキュリティチェックリスト
-
BETTER_AUTH_SECRETが設定されている(32 文字以上) - 本番環境で
advanced.useSecureCookies: trueが設定されている -
trustedOriginsが設定されている - レート制限が有効になっている
- メール認証が有効になっている
- パスワードリセットが実装されている
- 機密性の高いアプリでは 2 要素認証を使用している
- CSRF 保護が無効化されていない
-
account.accountLinkingを確認している
トラブルシューティング
| 問題 | 解決方法 |
|---|---|
| "Secret not set" | BETTER_AUTH_SECRET 環境変数を追加します |
| "Invalid Origin" | ドメインを trustedOrigins に追加します |
| Cookie が設定されない | baseURL がドメインと一致しているか確認し、本番環境でセキュア Cookie を有効にします |
| OAuth コールバックエラー | プロバイダーダッシュボードでリダイレクト URI を確認します |
| プラグイン追加後の型エラー | CLI の generate/migrate を再実行します |