api-auth-better-auth-drizzle-hono について
Better Authを使うTypeScript開発者向けの認証スキルです。設定、セッション、プラグイン、データベースマイグレーションを扱い、メールとパスワード、OAuth、二要素認証、組織単位のマルチテナントに対応します。
主な機能
- 01サーバー設定とデータベースアダプター
- 02型安全なセッションミドルウェア
- 03メール・パスワード認証フロー
- 04OAuthと二要素認証
- 05組織マルチテナント
- 06データベース、Cookieキャッシュ、ステートレスセッション
活用シーン
- 01TypeScriptアプリへのセルフホスト認証の追加
- 02型安全なセッションによるルート保護
- 03OAuthと二要素認証ログインの設定
- 04セッション方式の選択
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ agents-inc/ skills --skill api-auth-better-auth-drizzle-honoインストール後、Claude Code で/api-auth-better-auth-drizzle-honoを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
metadata.yamlreference.mdexamples/core.mdoauth.mdorganizations.mdsessions.mdtwo-factor.md詳細
Better Auth による認証
クイックガイド: TypeScript アプリで、型安全かつセルフホスト可能な認証を実現するには Better Auth(v1.5 以降)を使用します。メール/パスワード、OAuth、2FA、セッション、ステートレス認証、組織のマルチテナンシーを提供します。プラグインアーキテクチャにより、段階的に複雑さを高められます。セッションに依存するミドルウェアより前に認証ハンドラーをマウントし、オリジンをまたぐデプロイでは先に CORS を設定します。また、プラグインを追加した後は必ずスキーマを生成します。
<critical_requirements>
重要:このスキルを使用する前に
(セッションに依存する他のミドルウェアより前に、認証ルートへ Better Auth ハンドラーをマウントする必要があります)
(クライアントとサーバーのオリジンが異なる場合、認証ルートより前に CORS ミドルウェアを設定する必要があります)
(すべてのシークレット(clientId、clientSecret、BETTER_AUTH_SECRET)に環境変数を使用する必要があります。ハードコードは絶対にしないでください)
(プラグインを追加した後は、npx auth@latest generate を実行し、続けて ORM のマイグレーションツールを実行する必要があります)
(ミドルウェアで型安全にセッションへアクセスするには、auth.$Infer.Session 型を使用する必要があります)
</critical_requirements>
自動検出: Better Auth、betterAuth、createAuthClient、auth.handler、auth.api.getSession、socialProviders、twoFactor プラグイン、organization プラグイン、drizzleAdapter、セッション管理、OAuth プロバイダー、ステートレスセッション、cookieCache、genericOAuth、oAuthProvider、passkey、SCIM
使用する場面:
- セルフホスト可能な認証を構築する場合(ベンダーロックインなし)
- メール/パスワード、OAuth、2FA を一つのソリューションで利用する場合
- 組織/チーム管理を備えたマルチテナント SaaS の場合
- 型安全なセッション管理が必要な場合
- データベースに保存するセッション、またはステートレスセッションが必要なプロジェクトの場合
使用しない場面:
- メンテナンス不要のマネージド認証が必要な場合(ホスト型認証ソリューションを検討してください)
- ユーザーアカウントのないシンプルな静的サイトの場合
- サーバーレスのコールドスタートが重大な問題となるプロジェクトの場合(ただし、ステートレスモードで改善できます)
対象となる主なパターン:
- プラグインを使用したサーバー設定(auth.ts)
- セッションミドルウェアと型安全なルート保護
- メール/パスワード認証フロー
- OAuth プロバイダー(GitHub、Google、汎用 OAuth)
- 二要素認証(TOTP)
- 組織とマルチテナンシー
- セッション方式:データベース、Cookie キャッシュ、ステートレス
- データベースアダプターとの統合
- クライアント側の useSession フック
- パフォーマンス:実験的な JOIN、Cookie キャッシュ、ステートレスセッション
詳細なリソース:
- examples/core.md - サインアップ、サインイン、クライアント設定、データベースアダプター
- examples/oauth.md - GitHub、Google、汎用 OAuth プロバイダー
- examples/two-factor.md - TOTP の設定、有効化、検証
- examples/organizations.md - マルチテナンシー、招待
- examples/sessions.md - セッション設定、Cookie キャッシュ、ステートレス
- reference.md - 判断のフレームワーク、アンチパターン、バージョンに関する注意事項
基本方針
Better Auth は、TypeScript を第一に考え、セルフホスト可能な認証アプローチを採用しています。ベンダーロックインなしで、ユーザーデータを自分のデータベースに保持できます。プラグインアーキテクチャにより、まずはシンプルに始め、必要に応じて機能を追加して段階的に複雑さを高められます。
基本原則:
- 一貫した型安全性 -
auth.$Infer.Sessionを介して、セッション型がサーバーからクライアントへ引き継がれます - データベースを信頼できる唯一の情報源とする - セッションは自分の DB に保存されます(オプションでステートレスモードも利用できます)
- プラグインベースの拡張性 - 必要に応じて 2FA、組織、パスキー、SCIM、OAuth プロバイダーを追加できます
- フレームワークに依存しない - どの TypeScript Web フレームワークでも動作します
- パフォーマンス重視 - 実験的な JOIN(2~3 倍高速)、Cookie キャッシュ、ステートレスセッション
基本パターン
パターン 1:サーバー設定(auth.ts)
データベースアダプターを使って auth インスタンスを作成します。すべての認証設定の信頼できる唯一の情報源です。
// lib/auth.ts
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "@/lib/db";
const SESSION_EXPIRES_IN_SECONDS = 60 * 60 * 24 * 7; // 7 days
const SESSION_UPDATE_AGE_SECONDS = 60 * 60 * 24; // Refresh daily
export const auth = betterAuth({
database: drizzleAdapter(db, { provider: "pg" }),
emailAndPassword: {
enabled: true,
minPasswordLength: 8,
maxPasswordLength: 128,
},
session: {
expiresIn: SESSION_EXPIRES_IN_SECONDS,
updateAge: SESSION_UPDATE_AGE_SECONDS,
},
trustedOrigins: [process.env.APP_URL || "http://localhost:3000"],
});
良い理由: 名前付き定数によりセッションポリシーを監査でき、URL には環境変数を使用し、エクスポートするインスタンスを一つにしています。
// BAD: Magic numbers, hardcoded secrets, default export
const auth = betterAuth({
database: { url: "postgres://user:pass@localhost/db" },
session: { expiresIn: 604800 },
});
export default auth;
悪い理由: 認証情報をハードコードするとソース管理に漏えいし、マジックナンバーによってポリシーが分かりにくくなり、デフォルトエクスポートを使用しています。
メール認証と Drizzle アダプターの設定を含む完全なセットアップについては、examples/core.md を参照してください。
パターン 2:型安全なセッションミドルウェア
認証ハンドラーをマウントし、ルートでセッションにアクセスするための型付きミドルウェアを作成します。
// CRITICAL: CORS must be configured BEFORE auth routes
app.use("/auth/*", cors({ origin: APP_URL, credentials: true }));
app.on(["POST", "GET"], "/auth/*", (c) => auth.handler(c.req.raw));
// middleware/auth-middleware.ts - Type-safe session access
type AuthVariables = {
user: typeof auth.$Infer.Session.user | null;
session: typeof auth.$Infer.Session.session | null;
};
export const authMiddleware = createMiddleware<{ Variables: AuthVariables }>(
async (c, next) => {
const session = await auth.api.getSession({ headers: c.req.raw.headers });
c.set("user", session?.user ?? null);
c.set("session", session?.session ?? null);
await next();
},
);
良い理由: auth.$Infer.Session により c.get("user") に正しい型が適用され、認証より前に CORS を設定することでプリフライトの失敗を防ぎ、c.req.raw により Better Auth が必要とする Web 標準の Request を渡せます。
// BAD: No type annotation - c.user is any, bypasses type system
app.use("*", async (c, next) => {
const session = await auth.api.getSession({ headers: c.req.raw.headers });
c.user = session?.user; // any - no autocomplete
await next();
});
悪い理由: AuthVariables 型がないとアクセスがすべて any になり、プロパティを直接代入すると型付き Variables を迂回します。
保護されたルートのパターンについては、examples/core.md を参照してください。
パターン 3:プラグイン追加後のスキーマ生成
各プラグインはデータベーステーブルを追加します。プラグインの追加または変更後に CLI を実行してください。
# Step 1: Generate Better Auth schema (outputs ORM-specific files)
npx auth@latest generate
# Step 2: Generate migration with your ORM tool
npx drizzle-kit generate
# Step 3: Apply migration
npx drizzle-kit migrate
必ず 3 つの手順をすべて実行してください。Better Auth の migrate コマンドは Kysely アダプターでのみ動作します。Drizzle では generate と Drizzle Kit を使用してください。
パターン 4:メール/パスワード認証と認証確認
認証確認とパスワードリセットのコールバックを含めて、メール/パスワード認証を設定します。
export const auth = betterAuth({
database: drizzleAdapter(db, { provider: "pg" }),
emailAndPassword: {
enabled: true,
minPasswordLength: 8,
maxPasswordLength: 128,
requireEmailVerification: true,
sendResetPassword: async ({ user, url }) => {
await sendEmail({
to: user.email,
subject: "Reset password",
html: `<a href="${url}">Reset</a>`,
});
},
},
emailVerification: {
sendVerificationEmail: async ({ user, url }) => {
await sendEmail({
to: user.email,
subject: "Verify email",
html: `<a href="${url}">Verify</a>`,
});
},
},
});
良い理由: メール認証で偽のサインアップを防ぎ、パスワード要件をサーバー側で適用します。
エラー処理を含むクライアント側のサインアップ/サインインフックについては、examples/core.md を参照してください。
パターン 5:セッション戦略
トレードオフの異なる 3 つのセッション方式があります。
| 戦略 | DB が必要 | 取り消し可能 | 最適な用途 |
|---|---|---|---|
| データベース(デフォルト) | はい | はい | ほとんどのアプリ |
| Cookie キャッシュ+DB | はい | はい(遅延あり) | DB 負荷の軽減 |
| ステートレス | いいえ | いいえ(バージョンのみ) | エッジ/サーバーレス |
// Cookie cache: reduces DB hits by caching session in signed cookie
session: {
cookieCache: { enabled: true, maxAge: CACHE_SECONDS, strategy: "compact" },
}
// Stateless: omit database option entirely
const auth = betterAuth({
// No database = fully stateless
session: { cookieCache: { enabled: true, strategy: "jwe" } },
});
Cookie キャッシュ戦略:compact(最小、内部用)、jwt(標準、サードパーティで検証可能)、jwe(暗号化され、データを秘匿)。
完全な設定と取り消しパターンについては、examples/sessions.md を参照してください。
<red_flags>
注意事項
- シークレットのハードコード(ソース内の clientId/clientSecret)—環境変数を使用する必要があります
- 認証ルートの後に CORS を設定—プリフライトリクエストが失敗します
BETTER_AUTH_SECRET環境変数の設定漏れ—セッションが機能しません- プラグイン追加後のスキーマ生成漏れ—実行時にデータベースエラーが発生します
- 型指定のないセッションミドルウェア—TypeScript の型安全性が失われ、
c.userがanyになります - Drizzle アダプターで
auth.migrate()を使用—Kysely でのみ動作するため、generateと Drizzle Kit を使用してください auth.handler()の呼び出し時にc.req.rawがない—生の Web 標準 Request を渡す必要があります
注意点とエッジケース:
- Google がリフレッシュトークンを発行するのは初回の同意時のみです—
accessType: "offline"とprompt: "consent"を使用してください - GitHub OAuth アプリはリフレッシュトークンを発行しません(アクセストークンの有効期間は長いです)
- ステートレスセッションは個別に取り消せません。すべてを無効化するには
versionをインクリメントしてください - Cookie キャッシュの取り消しは、他のデバイスで
maxAgeが切れるまで遅延します - クロスドメインのデプロイでは、セッション Cookie に
SameSite=NoneとSecureが必要です authClient.forgotPasswordは v1.4 でauthClient.requestPasswordResetに改名されましたInferUser/InferSessionは v1.5 で削除されました。better-authの汎用UserとSession型を使用してください
アンチパターンのコード例、判断フレームワーク、バージョンに関する注意事項については、reference.md を参照してください。
</red_flags>
<critical_reminders>
重要な注意事項
(セッションに依存する他のミドルウェアより前に、必ず認証ルートに Better Auth ハンドラーをマウントしてください)
(クライアントとサーバーのオリジンが異なる場合、必ず認証ルートより前に CORS ミドルウェアを設定してください)
(すべてのシークレット(clientId、clientSecret、BETTER_AUTH_SECRET)には必ず環境変数を使用してください。ハードコードは絶対に避けてください)
(プラグインを追加した後は、必ず npx auth@latest generate を実行してから、ORM のマイグレーションツールを実行してください)
(ミドルウェアで型安全にセッションへアクセスするには、必ず auth.$Infer.Session 型を使用してください)
これらのルールに従わないと、認証の失敗、セキュリティ上の脆弱性、または実行時エラーが発生します。
</critical_reminders>