Upgrade to Pro — share decks privately, control downloads, hide ads and more …

-AIが認証し、AIが認証を書く- AI Agent 時代の認証ライブラリ Better A...

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Kaito.K Kaito.K
July 22, 2026
750

-AIが認証し、AIが認証を書く- AI Agent 時代の認証ライブラリ Better Authを理解する

Avatar for Kaito.K

Kaito.K

July 22, 2026

Transcript

  1. 00 — オープニング 認証基盤って結局何を選べばいいの? Better Auth です。 ※ 要件次第で他を検討 ここからは「なぜ」の積み上げ。歴史‧機能‧競合⽐較

    ‧AI認証の未来の順に根拠を重ねます。 前半が発表本編、後半に全詳細の Appendix。資料としてフル版を 共有します。 00 オープニング 01 Better Authとは 02 歴史 03 コア機構 04 認証⽅式 05 フレームワーク統合 06 プラグイン⼤全 07 Infrastructure 08 ⽐較 — なぜ他ではないのか 09 AI認証の未来 10 おわりに
  2. 01 — Better Authとは 認証サービスの2つの流派 HOSTED SAAS SELF-HOSTED LIBRARY ホスト型

    SaaS ⾃前ホスト型ライブラリ Auth0 / Clerk / Cognito / Firebase / Kinde / WorkOS Better Auth / Auth.js ユーザーデータはベンダー側に置かれる 本質は「データを誰が持つか」。 ユーザーデータは⾃分の DB に残る
  3. 01 — Better Authとは Better Auth の定義と規模 ⾃分のコードベースとデータベースの中で完結する、 TypeScript ファーストの包括的な

    認証フレームワーク フレームワーク⾮依存 OSS‧MIT BYODB(⾃分のDB) ヘッドレス プラグイン拡張 470万+ 850⼈+ 2年 週間 npm ダウンロード コントリビューター 公開から買収までの期間
  4. 01 — Better Authとは auth.ts 1ファイルから始まる -/ auth.ts -/ route

    handler にマウント import { betterAuth } from "better-auth"; export const { GET, POST } = toNextJsHandler(auth.handler); export const auth = betterAuth({ database: -* pg / prisma / drizzle --. -/ emailAndPassword: { enabled: true }, -/ lib/auth-client.ts socialProviders: { import { createAuthClient } from "better-auth/react"; google: { clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret : process.env.GOOGLE_CLIENT_SECRET!, }, export const auth = createAuthClient({ -/ Auth Server の URL }, baseURL: “http:-/localhost:3000” }); }); -/ クライアントから await authClient.signIn.email({email,password });
  5. 02 — 歴史 Better Authのはじまり② ほとんどの⼈はそういうことを考えてい るのか! “Better Auth”って名前よくないか?! npmで”Better

    Auth”が利⽤可能な ら、フレームワークに依存しないプラ グインで拡張できる認証フレームワー クを作ることにしよう!
  6. 02 — 歴史 寝室での開発 から Vercel 買収まで — 2年のタイムライン 開発開始

    アディスアベバ ⾃宅の寝室を中⼼に 開発 2024 YC X25 採択 $5M シード Auth.js 保守移管 Vercel 買収発表 GitHub 公開 GitHub API 確認済み Spring 2025 Peak XV 主導 Discussion #13252 額⾮公開‧MIT 継続 2024-09 2024-11-23 2025-06-25 2025-09 2026-07-07 v1.0.0 2025 春
  7. 02 — 歴史 Auth.js 合流、そして Vercel 買収へ 2026-07-07 — Vercel

    買収発表 01 創業者とコアチームが Vercel に合流 02 Next.js + Auth.js + Better Auth — 認証レイヤーの垂直統合 03 狙い = 「アプリとAI エージェント向け OSS 認証の加速」 2025-09 — GitHub Discussion #13252 “Auth.js is now part of Better Auth” NextAuth ユーザーの進化先は事実上 Better Auth に。公式移⾏ガ イドあり。 OSS(MIT)継続を明⾔
  8. 03 — 機能総覧 / コア機構 コア機構 — できること総覧 機構 できること

    auth.handler Web 標準の単⼀関数。catch-all ルート1本に挿すだけで全エンドポイントが動く auth.api 同じ機能をサーバー内部から型安全な関数として直接呼べる(失敗時は APIError を throw) CLI generate / migrate でスキーマ⾃動⽣成 — 認証テーブルを⼿書きしない Client React / Vue / Svelte / Solid / vanilla の5パス。useSession 購読‧{ data, error } 設計 Session Cookie ベース‧7⽇ローリング更新。1台だけ / 全部の失効 API、Redis 退避、cookieCache Cookies すべて secret で署名。compact / jwt / jwe の3⽅式‧サブドメイン共有 Hooks エンドポイント before / after + databaseHooks — プラグインを書かずに振る舞いを差し込む Rate limit 本番は既定で有効(60秒 / 100回)。パス単位の customRules User / 型安全 additionalFields でスキーマ拡張‧accountLinking‧$Infer で型がクライアントまで通る 詳細は Appendix §03 へ
  9. 04 — 機能総覧 / 認証方式 認証⽅式 — できること総覧 ⽅式 できること

    導⼊ Email & Password サインアップ / イン‧メール検証‧パスワードリセット‧ 列挙攻撃対策(OWASP 準拠)‧ハッシュ差し替え(scrypt → Argon2id) emailAndPassword: { enabled: true } のみ ソーシャルログイン Google‧Apple‧GitHub‧LINE‧Kakao‧Naver など組み込み30種超。 プロフィールマッピング‧コールバック処理込み clientId / clientSecret を渡すだけ Generic OAuth OAuth 2.0 / OIDC 準拠なら何でも接続 — 社内 IdP‧Auth0‧Keycloak‧Okta‧独⾃ OAuth discoveryUrl 1⾏ or プリセットヘルパー8種 パスワードレス Magic Link(メールリンク)‧Email OTP‧ Passkey(WebAuthn / ⽣体)‧電話番号 SMS プラグイン1⾏ + スキーマ再⽣成 多要素‧その他 2FA(TOTP / OTP / バックアップコード)‧ SIWE(ウォレット署名)‧匿名ユーザー → 本登録 プラグイン1⾏ + スキーマ再⽣成 詳細は Appendix §04 へ
  10. 05 — 機能総覧 / フレームワーク統合 フレームワーク統合 — 対応総覧 Request →

    auth.handler → Response — どこでもこの1本を挿すだけ カテゴリ 対応 やること フロント / フルスタック Next.js‧Nuxt‧SvelteKit‧SolidStart‧Astro‧ React Router / Remix‧TanStack Start catch-all ルート1本に公式ヘルパー バックエンド Hono‧Fastify‧Express‧Elysia‧Nitro‧NestJS‧Convex ワイルドカードルートに auth.handler モバイル / デスクトップ Expo‧Lynx‧Electron 既存サーバーを流⽤ + クライアントプラグイン ランタイム Node.js‧Deno‧Bun‧Cloudflare Workers Web 標準の Request / Response が動けば OK 詳細は Appendix §05 へ
  11. 06 — 機能総覧 / プラグイン (1/2) プラグイン総覧① — 認証‧認可‧企業 認証系(

    10) 認可・承認系( 5) Two-Factor TOTP‧OTP‧バックアップコードの⼆要素認証 Admin ユーザー管理‧BAN‧なりすまし Passkey WebAuthn / ⽣体認証。フィッシング耐性 API Key キー発⾏‧検証‧レート制限 Magic Link メールリンクでパスワードレス Organization 組織‧チーム‧招待‧RBAC Email OTP コード1つでサインイン‧検証‧リセット MCP ⾃アプリを OAuth プロバイダ化 Phone Number 電話番号 + SMS OTP Agent Auth AI エージェントの識別‧認可(→ §09) Username ユーザー名でもログイン 企業系( 4) Anonymous ゲスト体験 → 後から本登録へリンク OIDC Provider ⾃社をログイン基盤にする One Tap Google ワンタップログイン OAuth Provider OIDC + MCP の後継統合 SIWE Ethereum ウォレット署名で認証 SSO 企業 IdP(SAML / OIDC)を消費 Generic OAuth 任意の OAuth2 / OIDC を追加 SCIM Okta / Entra からディレクトリ同期 詳細は Appendix §06 へ
  12. 06 — 機能総覧 / プラグイン (2/2) プラグイン総覧② — ユーティリティ‧決済 ユーティリティ(

    12) 決済(7) Captcha Turnstile / reCAPTCHA でボット対策 Stripe 直接 PSP。サブスク‧Webhook ⾃動処理 JWT 外部連携⽤トークン + JWKS 検証 Polar MoR — 税を丸投げ + 特典⾃動配布 OpenAPI 全エンドポイントのリファレンス UI Autumn Stripe の上の従量‧クレジット課⾦ Multi-Session 複数アカウントの同時ログイン Dodo Payments 150+カ国のグローバル MoR Have I Been Pwned 漏洩済みパスワードを拒否 Creem MoR + 収益分配(レベニュースプリット) Bearer Token Cookie の代わりにトークン認証 Chargebee エンプラ向けサブスク管理層 Device Authorization CLI‧TV‧IoT のログイン Commet AI / API 従量課⾦の MoR OAuth Proxy プレビュー環境の redirect 問題を解消 One-Time Token クロスドメインの受け渡し Last Login Method 「前回は Google」表⽰ i18n エラー⽂⾔の多⾔語化 Test utilities 認証フローのテスト⽤ヘルパー MoR = 販売者を肩代わりし税/VAT の申告‧納税まで代⾏するモデル。導⼊ はどれも「plugins: [] に1⾏ + スキーマ再⽣成」。 詳細は Appendix §06 へ
  13. 07 — 機能総覧 / Infrastructure Infrastructure — ⼊れると何が⼿に⼊るか ⼿に⼊るもの 具体的には

    プラグイン / プラン 管理画⾯ ユーザー‧組織‧セッションを GUI で検索‧BAN‧なりすまし。 統計と監査ログは⾃動収集 dash()‧無料〜 攻撃を防ぐ⼒ 総当たり‧ボット‧使い捨てメール‧トライアル悪⽤‧ 不可能移動を検知し、記録 → チャレンジ → 遮断 sentinel()‧Pro 以上 届くメール 検証‧リセット‧招待メールをテンプレート13種でマネージド配信 (SES / SendGrid / Resend) Email Service‧Pro 以上 企業要件への回答 SSO(SAML)‧SCIM ディレクトリ同期‧SIEM へのログ転送 Enterprise コア(認証機能)はどこまでも無料。有料なのは「運⽤」だけ —DB とユーザーデータは⾃前のまま。 詳細は Appendix §07 へ
  14. 08 — 比較 総合⽐較表 プロダクト 形態 データ所有 型安全 UI 提供

    料⾦(2026前半検証‧要再確認) AI対応 Better Auth OSS ライブラリ(MIT)/ ⾃前ホスト ⾃分の DB ◎ ×(ヘッドレ ス) 無料(OSS)。運⽤は Infra(有 ◎ Agent Auth 料)で任意 Auth0 ホスト型 SaaS (Okta 傘下) ベンダー側 ◦ ◎ Universal Login 無料25K MAU → $35/mo〜‧超過 △ $0.07/MAU Clerk ホスト型 SaaS ベンダー側 ◦ ◎ プリビルト 無料50K MRU → Pro $25/mo + $0.02/MRU △ WorkOS ホスト型 SaaS (B2B 特化) ベンダー側 ◦ ◦ AuthKit AuthKit 1M MAU 無料 / SSO $125/接続/mo ◦ auth.md Kinde ホスト型 SaaS (認証+課⾦+フラグ) ベンダー側 ◦ ◦ 無料10.5K MAU → Pro $25/mo〜 △ Supabase Auth BaaS ⼀体型(GoTrue) Supabase 内 ◦ △ プラン内(Free 50K MAU / Pro $25/mo〜) OpenAuth OSS 認証サーバ / ⾃前ホスト ⾃分の DB ◦ × 無料(OSS)。運⽤コスト⾃⼰負 △ 担 Auth.js OSS ライブラリ / ⾃前ホスト ⾃分の DB ◦ × 無料(保守は Better Auth チーム △ へ移管済み) ※ 価格は 2026-07 検証‧登壇直前に要再確認。Clerk は MRU(retained users)、他社は MAU と課⾦単位が異なる。 △
  15. 08 — 比較 なぜ他ではないのか — 総集編 競合 良い点 でも Auth0

    業界標準。エンタープライズ実績は随⼀ データはベンダー側。MAU 従量(超過 $0.07/MAU)でスケール時に⾼ 額化 Clerk プリビルト UI で導⼊最速。B2C 定番 セッション‧署名鍵‧ユーザーレコードを⾃分で所有できない WorkOS エンプラ SSO / SCIM の王者 B2B 特化でスタック委譲が前提 Kinde 認証 + 課⾦ + フラグの統合 ロックイン構造は Clerk と同型 Supabase Auth Supabase 使いなら⾃然な選択 BaaS 密結合(GoTrue)— 認証だけ切り出せない OpenAuth 同じ OSS‧セルフホスト思想 認証サーバーを別に⽴てる思想。プラグイン級の網羅なし 各社の詳細⽐較は Appendix §08 へ。
  16. 08 — 比較 / 訂正欄 デメリット 主要な注意点 小さめの注意点 1 歴史が浅い

    — まだまだ採⽤事例が少ない。 6 コミュニティプラグインの品質ばらつき — 本番採⽤前にメンテ状 況‧中⾝を⾃分の⽬で。 2 破壊的変更リスク — 進化が速い分 API が動く。バージョン固定 + 検証環境で先に試 す。 7 TS/Node‧RDB 前提が強い — ⾮ TS‧NoSQL は⼀級市⺠ではな い。スタックが外れるなら他も⽐較。 3 ⾃前ホスト = 運⽤責任は⾃分 — メール‧スケール‧パッチ‧セキュリティなど全て が⾃分の責務。⾃由の代償。 4 プラグイン追従の⼿間 — 追加のたび generate / migrate。1つずつ⾜して都度確認が 安全。 5 Infrastructure(有料)依存の芽 — 寄せすぎるとロックインとなる(→ 7-11)。線 引きは設計段階で必要。 弱点の多くは「新しい OSS」「⾃前ホスト」の裏返し。データ所有 ‧型安全‧網羅性‧AI ネイティブがコストを上回るか — その⼀点 で判断する。
  17. 08 — 比較 判断軸のまとめ データ⾃社 + TS フルスタック Better Auth

    50K MAU 未満の B2C を最速で Clerk も合理的 エンタープライズ SSO 最優先 WorkOS も合理的 それでも答えは Better Auth — 型安全‧データ所有‧網羅、そして第9章。
  18. 09 — AI認証の未来 あなたのアプリを使うのは、もう⼈間だけじゃない 57.5% 20% 970倍 Web トラフィックの過半が bot

    に — 史上 初の逆転 Cyber Week の全注⽂の2割に AI が関与 MCP SDK の⽉間 DL — 18か⽉で10万 → 9,700万 主因は agentic AI。Cloudflare Radar(2026-06) AI 経由流⼊は前年⽐ +393%‧CV 約42%⾼。 Salesforce / Adobe(2025-12〜2026 Q1) 公開 MCP サーバーは1万超。Anthropic (2025-12〜2026-03) 利⽤者に AI が加わった。では、その AI をどう受け⼊れる? ※ Gartner 予測: 2028年に B2B 購買の90%が AI エージェント経由($15兆)
  19. 09 — AI認証の未来 2軸フレーム — 「AIと認証」の2つの向き AXIS 1 AXIS 2

    軸① AI が認証を書く 軸② AI が認証される 問い AI に実装させられるか 問い エージェント⾃⾝を受け⼊れ、認証できるか 主役 開発者 + コーディング AI 主役 AI エージェント 答え CLI‧MCP‧Skills‧llms.txt‧Ask AI 答え Agent Auth‧auth.md ⇄ Better Auth = 実装の⾃動化 = 認証される主体の追加 SaaS は軸①でブラックボックス化しがち。Better Auth はコードベース型 OSS を武器に両軸を同時に押さえる。
  20. 09 — 軸② AI が認証する 既存の認証は「⼈間 + 静的アプリ」しか想定していない エージェントは短命タスクから常駐ワーカー、多段の⾃律システム ま

    で幅がある。 既存モデル(OAuth・セッション・API キー) ⼈間のユーザー 静的アプリ 事前定義スコー プ AI エージェント = 第3のアクター(モデルの外側) ⼈間の介在なしに、ユーザーの代理で、時に⾃分の判断 で外部サービ スを呼ぶ。 — ⼈間でも静的アプリでもない。既存の認証モデルにそのまま当ては まらない。
  21. 09 — 軸② AI が認証する 問題 — Delegated Agents(継承された identity)

    ユーザーの鍵 1本 (OAuth トークンやAPI キー) �� 可視性なし どのエージェントのリクエストか判別できない ↓ ユーザーの全権限を全員で共有 🤖 🤖 🤖 Agent A Agent B Agent C スコープなし 資格情報を共有する全エージェントが同じ権限 分離なし 1体だけ失効できない サーバーからは全部「同じユーザー」に⾒える — ⽌めるなら全停⽌しかない = 監査不可‧最⼩権限が効かない‧事故時の封じ込め不可。
  22. 09 — 軸② AI が認証する Agent Auth Protocol(v1.0-draft)— 独⽴ principal

    化 Agent はユーザーの権限を借りるシステムに存在しない主体から、システムの登場⼈物として識別されるようになる AI エージェントの認証‧capability ベース(できること単位ベースの)認可 ‧サービス発⾒(Agentが訪問したシステムについて⾃⼒で理解す る仕組み)のオープンな標準仕様を提供 + Better Auth側でSDK(エージェント‧サーバー側の実装)およびPluginが提供されている、という実 装⾯もカバー。identity 継承の代わりに、各エージェントが固有の以下4つを持つ �� identity どのエージェントかをサーバーが識別できる固有の⾝元 暗号鍵ペア エージェント⾃⾝の鍵。リクエストへの署名に使う identity scoped capabilities 最⼩権限で絞れる範囲付きの能⼒ 鍵ペア 独⽴ライフサイクル そのエージェントだけを発⾏‧更新‧失効できる 1エージェント = 1バッジ capabilities ライフサイクル
  23. 09 — 軸② AI が認証する 3つの⽋落は、こう解消される 可視性なし → 🤖 🤖

    🤖 Agent A Agent B Agent C 🔑 ⾃分の鍵 🔑 ⾃分の鍵 🔑 ⾃分の鍵 notes:read deploy:run pay:limit ⏻ 個別失効 ⏻ 個別失効 ⏻ 個別失効 固有 identity で clear attribution どの⾏為を誰(どのエージェント)がやったか、 明確に帰属させられる) スコープなし → エージェントごとに capability(できること) 付与(least privilege) 分離なし → 独⽴ライフサイクルで個別失効 結果: Claude / ChatGPT / Cursor のようなアプリが銀⾏‧API‧デプロイパイ プラインへ、帰属明確 + 権限最⼩でタスク実⾏できる。
  24. 09 — 軸② AI が認証する 仕様の範囲と3つの役割 SPECIFICATION — 7項目 identity

    capabilities lifecycle registration approval Servers 認可と capability 管理を⾏う側 Client エージェントとサーバーをつなぐブリッジ Agents 実⾏時の AI アクター本体 authentication discovery
  25. 09 — 軸② AI が認証する フロー — discovery → registration

    → capability authorization 1 Agent → Server GET /.well-known/agent-configuration → capabilities ⼀覧を取得 2 Agent capabilities を⾒て「何が必要か」を判断 3 Agent → Server register + capability grant をリクエスト 4 Server ⇄ User(承認) device_authorization(ユーザーコードのブラウザ承認)or ciba (バックチャネル)→ capability grant 発⾏ 5 Agent → Server 短命 JWT(aud = 呼び先 URL)に署名し、default_location(または capability 個別の location)で実⾏ ※ base path が /api/auth でも、発⾒ルートは /.well-known/agent-configuration に置く。
  26. 09 — 軸② AI が認証する 従来⼿法との⽐較 観点 OAuth API キー

    Delegated(継承) Agent Auth エージェント識別 不可(アプリ単位) 不可(キー単位) 不可(溶け込む) 可(principal ごと) 権限の粒度 事前定義スコープ キーに紐づく固定 共有 = 同⼀権限 capability 個別付与 個別失効 困難 キー失効で全停⽌ 不可 可(独⽴ライフサイクル) ライフサイクル概念 弱い なし なし あり(仕様の⼀部) FAQ「OAuth の置き換え?」→ No。別問題を解く。併存できる。
  27. 09 — 軸② AI が認証する MCP との関係 — 「MCP の

    auth で⾜りる?」→ No MCP の OAuth 2.1 だけの場合 �� �� �� ↓ 潰れる MCP + Agent Auth 併存 �� �� �� A B C ↓ 個別に⾒える サーバーには「1クライアント」にしか⾒えない capability は MCP ツールとして公開、identity と認可は Agent Auth per-agent identity‧capability 認可‧ライフサイクル概念を持たな い。 層が違うから併存できる — MCP はツール提供、Agent Auth は「誰が ‧何を許されているか」。
  28. 09 — 軸② AI が認証する エコシステムと⽴ち位置 保守は Better Auth チーム。ただし

    Better Auth ⾮依存 — 任意のプラットフォームが独⽴採⽤できるオープン標準。 SDK Directory Community Demo /docs/sdks agent-auth.directory Discord /demo
  29. 09 — 軸② AI が認証する Better Auth の agent-auth プラグインが実装するもの

    ✓ identity‧registration‧discovery‧capability 認可を公式プラ グインとして組み込み済み ✓ /.well-known/agent-configuration ルートを⽣やす ✓ 承認⽅式 device_authorization / ciba をサポート -/ app/.well-known/agent-configuration/route.ts import { auth } from "@/lib/auth"; import { NextResponse } from "next/server"; export async function GET() { -/ プラグインが組み立てた設定を返すだけ const config = await auth.api.getAgentConfiguration(); ✓ 短命 JWT(aud ⼀致)署名で capability 呼び出し 2軸の交差点 : 軸①の CLI / プラグイン体験の上に、軸②の「AI が認証さ れる」機能が乗る。 return } NextResponse.json(config);
  30. 09 — 軸② AI が認証する / auth.md AUTH.md とは —

    WorkOSがlaunchしたエージェント向けの「会員登録案内」 robots.txt クローラーに「巡回のルール」を伝えるテキスト llms.txt LLM に「⽂書の索引」を渡すテキスト AUTH.md AI エージェントに「このサービスへの登録⼿順書」を渡すテキスト どこに置く? つまり? サービスのルート直下 — https:-/service.example.com/auth.md 。 エージェントは docs‧SDK‧401 レスポンスの WWW-Authenticate ヘッダ から「⼈間と同じように」発⾒する サインアップフォーム(⼈間の UI)の代わりに、「エージェントが読める 登録の契約書」をドメインに置く発想 注意 中⾝は? 番号付きの⼿順書: 発⾒ → ⽅式選択 → 登録 → claim → トークン交換 → 利 ⽤ → 失効対応。コードブロックはそのままリクエストのテンプレートとし て抽出される 正式な情報源は PRM(/.well-known/oauth-protected-resource)— auth.md はそれを⼈間にもエージェントにも読める形にした補⾜資料。⽭ 盾したら PRM が正
  31. 09 — 軸② AI が認証する / auth.md AUTH.md— ドメインに置く1枚の Markdown

    狙い = 「サインアップフォーム(⼈間の UI)なしでエージェントがユーザーを登録する」。典型は https:-/service.example.com/auth.md。 # auth.md — Notes App -# Supported flows - agent-verified # IdP が保証 - user-claimed # ユーザーがコードで確認 -# Scopes - notes:read - notes:write ノートの閲覧 ノートの作成・編集 -# Registration - discovery: .well-known/oauth-authorization-server identity endpoint: POST /agent/identity - token endpoint: POST /oauth2/token (jwt-bearer) -# After registration - access_token を Bearer で付与。失効時は再登録 → ⼈間の統合担当者が読むドキュメント AUTH.md エージェントが実⾏時に発⾒して読むランタイ → ム成果物 記述4点: 対応フロー / 公開スコープ / 登録⼿順 / 登録後の動作。プ レーンテキストだから両⽅に効く。
  32. 09 — 軸② AI が認証される / auth.md auth.md に書いてあること —

    4節総覧 節 何を書くか ⼈間の世界で⾔うと Supported flows どの登録⽅式を受けるかの宣⾔(verified / claimed / 両対 店頭の「使える⽀払い⽅法: カード / QR」の掲⽰ 応) Scopes サービスが公開する権限メニュー(notes:read / 会員種別ごとの「できること」⼀覧 notes:write)。エージェントは必要な分だけ申請し、トー クンはその範囲に限定 Registration 登録⼿続きの窓⼝ URL ⼀覧(discovery / identity / token — 仕様上は claim‧events‧revocation 含め6窓⼝) After registration 登録完了後のトークンの使い⽅と運⽤ルール(Bearer 付与 会員証の利⽤規約 ‧失効時は再登録) 「新規登録はこちら」ボタンの機械可読版 ※ 登場⼈物は最⼤3役(Agent / Agent Provider / Service)— verified では IdP(Provider)が⾝元保証に⼊り、claimed では⼈間の確認で代替する。
  33. 09 — 軸② AI が認証される / auth.md たとえで掴む — 店員「きみ、誰?」

    ロボット(エージェント)に「ノートアプリに私のメモを保存して」と頼んだ。ロボットが店に着くと、店員に⽌められる — 「 本当にこの⼈の 使いなの?証明できる? 」。証明のやり⽅が2つある、というだけの話。 AGENT-VERIFIED 「⾝分証を⾒せる」 ロボットを動かしているアプリ(親元 = IdP)が「この者は本⼈の使 いです」と書いた⾝分証を発⾏し、偽造できないハンコ(電⼦署 名)を押す。店員はハンコを照合して通す。 本⼈は店に⾏かなくていい — 事前に「押していいよ」(consent)と 伝えてあるだけ。 ⾝分証 = ID-JAG / 照合 = JWKS 検証 USER-CLAIMED 「本⼈がその場で引き取る」 ⾝分証がない場合。店員「番号札 XK7 を渡すから本⼈に確認させ て」→ 本⼈が⾃分のアカウントでログインし(ログインできる = 本 ⼈の証明)「この番号のロボットは私の使いです」とボタンを押 す。 gh auth login のデバイス認証と同じ体験。 親元(IdP)不要‧毎回ワ ンタップ 違いは⼀⾏ — 「⾝分証を⾒せる」か「本⼈に確認する」か。もらえる⼊店証(トークン)は同じもの。
  34. 09 — 軸② AI が認証される / auth.md 3つの役割と ID-JAG Agent

    Agent Provider(IdP) ユーザーの代理 ID-JAG を発⾏ ID-JAG = Identity Assertion JWT Authorization Grant ⾝元アサーションを認可グラントとして使う仕組み。IETF OAuth ド ラフト draft-ietf-oauth-identity-assertion-authz-grant に 基づく。 ⇄ ID-JAG ⇄ Service assertion を受理し scoped アクセスを発⾏ ID-JAG(署名付き⾝元保証書) → 交換 → scoped access_token(これが利⽤券) → Service の API を利⽤ ※ ID-JAG は利⽤券ではなく「引換の⼿前の⾝元保証書」— サインアップ画⾯なしで登録‧トークン発⾏まで進むための証明。
  35. 09 — 軸② AI が認証される / auth.md ID-JAG — 実印つきの「紹介状」

    普通は窓⼝(= ログイン画⾯)で申込書を書く。ID-JAG は、信頼する銀⾏が発⾏した実印つき紹介状を持ってくれば、申込書なしで会員証を発 ⾏する。紹介状には宛先(audience)が書いてあるから、別の店では使い回せないようになっている 👤 User(あなた) 事前に⼀回だけ承諾 ① consent 「紹介状を書いていいよ」 🏦 ② 実印つき紹介状を発⾏ = ID-JAG Agent Provider (信頼する銀⾏) 🤖 ③ 紹介状を提出 POST /agent/identity 🏪 Agent 店(Service) 紹介状を携えて店(Service)へ ④ JWKS(銀⾏(Provider) の公開鍵) で 実印を照合 → ⑤ 会員証(トークン)発⾏ エージェントの所属元 (IdP) 📜 紹介状(ID-JAG) =「この者は本⼈の代理です」+ 実印(Providerのハンコ) + 宛先 (audience) → 引換 → 🎫 会員証(scoped access_token) 紹介状には宛先が書いてあるから、別の店では使い回せない(audience 固有)。紹介状 ≠ 会員証 ― 引換の⼿前の証明書
  36. 09 — 軸② AI が認証される / auth.md Agent verified flow

    — IdP がユーザーを保証(8段階) 1〜3 発⾒(401 を起点に⾃⼒で探る) 4〜5 保証書の⼊⼿(consent → ID-JAG) 6〜8 提出‧検証‧交換 1 Agent → Service GET /api/resource → 401 WWW-Authenticate(resource_metadata) 2 Agent → Service GET .well-known/oauth-protected-resource → PRM(authorization_servers) 3 Agent → Service GET .well-known/oauth-authorization-server → AS metadata(agent_auth ブロック) 4 Agent ⇄ User consent —「この audience に identity を主張してよいか」 5 Agent → Provider audience 固有の ID-JAG を要求 → 発⾏ 6 Agent → Service POST /agent/identity(type: identity_assertion, assertion: ID-JAG) 7 Service → Provider GET .well-known/jwks.json — Provider の JWKS で署名検証 8 Agent → Service POST /oauth2/token(grant_type=jwt-bearer)→ scoped / short-lived / revocable な access_token ※ ⼈間が出るのはステップ4の consent ⼀回だけ — 委任状にハンコを押したら、あとは全部機械同⼠。実仕様では 6 の提出後に Service が⾃前署名の identity_assertion を返し、それを 8 で access_token に交換する⼆段交換。
  37. 09 — 軸② AI が認証する / auth.md User claimed flow

    — IdP 不要、ユーザーがコードで確認 auth.md の情報だけでエージェントが⾃⼰ナビゲートできる(エージェント側の特別な統合が不要)。 1 auth.md を取得し claimed フローを選択 4 ユーザーがサインインしコードを claim → → 2 登録要求 → 確認コードを受領 5 scoped access_token に交換 → → 3 ユーザーにコード + サインイン URL を提⽰ 6 API 呼び出し。revoke 時は再登録
  38. 09 — 軸② AI が認証される / auth.md verified vs claimed

    — どう使い分けるか agent-verified(8段階) user-claimed(6段階) 本⼈性の保証 ID-JAG(IdP の署名) ⼈間のサインイン + コード確認 Provider(IdP) 必要 不要 — ⼈間の確認で代替 署名検証(JWKS) Service が実施 なし ⼈間の登場 事前の consent ⼀回だけ(委任状のハンコ) 毎回の登録で動線の真ん中に登場 エージェント側の実装 IdP との統合実装が必要 auth.md を読むだけで⾃⼰ナビゲート 最終成果物 scoped access_token scoped access_token(同じ) 向いている場⾯ スケールする — ⼤量エージェントの⾃動‧組織的運⽤ ⼿軽 — 個⼈が⾃分のエージェントを1体つなぐ どちらを受けるか(verified だけ / claimed だけ / 両対応)はサービス側が Supported flows で宣⾔する — 店頭の「使える⽀払い⽅法」の掲⽰。
  39. 09 — 軸② AI が認証される / auth.md 発⾒の2パターン — どこから⼿順に⼊るか

    パターン B — 先読み パターン A — 主経路 先に auth.md を読んでから⾏く まず API を叩いて、ぶつかる GET /api/resource(トークン無し) → 401 + WWW-Authenticate ヘッダに「認証⽅法はここを読め」のヒン ト → ヒントを辿って auth.md / .well-known を読み、Step 1 から進む ⾨前払いは正常動作 — 「ぶつかってから案内所に来る」が標準の旅程。 「このサービスと連携して」と頼まれ、まだ API を叩いていない(= 401 を持っていない) → 慣例パス /.well-known/oauth-protected-resource を直接 取得(仕様が明記) → 同じ⼿順に合流。登録完了までは API を叩かない スキップされるのは「401 を⾷らう体験」だけ — discovery ⾃体は必 ず踏む("do not skip ahead")。 どちらも Step 2 以降(register → 保証 → exchange)は完全に同⼀。
  40. 09 — 軸② AI が認証される / auth.md エージェントが読む6段階の⼿続きレシピ discover →

    register → claim → exchange → use → handle revoke ↺ revoke を受けたら discover へ戻る discover = auth.md + .well-known を取得 / register‧claim = verified or claimed で登録‧確認 / exchange = scoped access_token に交換 use = Bearer で API 呼び出し / handle revoke = 失 効で停⽌‧再登録。定義元は workos/auth.md の AUTH.md(skill manifest) ※ 運⽤中に 401 → まず exchange(トークン再交換)を1回試す → だめなら discover からやり直し。refresh_token は存在せず、この2段が代替。⼿順は 「Follow the steps in order; do not skip ahead」— auth.md を先に読んだ場合も discovery は省略しない。
  41. 09 — 軸② AI が認証される / auth.md 信頼 / セキュリティモデル

    短命 scoped audience 固有 ✓ 資格情報 = ユーザーに紐づく scoped access token。 標準 OAuth で 発⾏ (既存 API 認証を再利⽤) ✓ verified では Provider の JWKS で ID-JAG 署名を検証。アサーショ ンは audience 固有で 使い回し不可 (audience = トークンの「宛 先」。宛先限定発⾏なので他所では無効) 失効可能 ✓ consent が明⽰的に挟まる。Provider は失効イベントを送れる ✓ どのフローを受けるか(verified / claimed / 両⽅)も、発⾏する資 格情報も アプリ側が主導権
  42. 09 — 軸② AI が認証する / auth.md github.com/workos/auth.md — 仕様本体

    + 参照実装 ├── AUTH.md # skill manifest ├── agent-services/ # resource + authz server 読み⼿別の⼊⼝ ├── agent-providers/ # ID-JAG 発行のサンプル IdP → エージェント実装者 → AUTH.md(⼿続きレシピ) └── shared/ # 共有パッケージ → サービス実装者 → agent-services/README(実装ガイド‧シーケン ス図‧エラー表) → IdP 実装者 → agent-providers/README(ID-JAG 発⾏‧JWKS 公開‧ 失効イベント) WorkOS 製だが仕様はオープン。
  43. 09 — 軸② AI が認証する Agent Auth と AUTH.md の棲み分け

    — 競合ではなく層が違う 観点 Agent Auth(Better Auth / AAP) AUTH.md(WorkOS) 主な問い 固有 identity をどう与えるか どう登録‧発⾒させるか 焦点 identity‧capability‧lifecycle registration(サインアップ無しの登録) 形 プロトコル + SDK + 公式プラグイン 1枚の Markdown + 参照実装 発⾒ルート /.well-known/agent-configuration auth.md + /.well-known/oauth-* 保守 Better Auth チーム WorkOS 開放性 オープン(Better Auth ⾮依存) オープン(WorkOS 著) 資格情報 暗号鍵ペア + scoped capabilities OAuth の scoped‧短命‧失効可能トークン 共通ゴール エージェントを「誰かの identity の影」から独⽴した主体へ 共通の⼟台 = OAuth / JWT / .well-known 標準
  44. 09 — 軸② AI が認証される たとえで掴むAgent Auth ProtcolとAUTH.md — パスポート

    vs 会員証 AUTH.MD AGENT AUTH PROTOCOL 店ごとの会員証 パスポート エージェント本⼈が持ち歩く⾝分証。鍵ペアを⾃分で⽣成し、秘密 鍵(実印)で⾝元を証明 — どのサービスに⾏っても同じ「私はエー ジェント X」を名乗れる。 identity はエージェントに宿る。 焦点 = identity‧capability‧lifecycle ⼊店のたびにその店の台帳に登録して発⾏してもらう。店 A の会員 証は店 B で使えない(audience 固有)。verified はパスポート (ID-JAG)を⾒せて作り、claimed は本⼈が窓⼝まで同⾏して作 る。 発⾏主体はサービス側。 焦点 = registration(サインアップ無しの登 録) ※ auth.md 内も役割は2段 — ⾝元を保証するのは verified なら IdP、claimed なら⼈間の claim 操作。 トークンを発⾏するのは常に Service (保証を受けて、⾃店でだけ使える会員証を発⾏する係)。 ⾝分証の発想と、会員登録の発想 — 層が違うので競合ではなく補完。
  45. 09 — AI認証の未来 / まとめ まとめ — 認証は「⼈間の UI」から「機械が読む契約」へ ドキュメント

    llms.txt 読める構造化テキストになる 認証フロー AUTH.md 発⾒‧実⾏できるランタイム成果物になる エージェントの⾝元 Agent Auth Protocol 識別‧認可‧失効できる principal になる 確定 Vercel × Better Auth の現在地 推論 ① 買収発表で「アプリとエージェント 向け OSS 認証の加速」を明⾔ (2026-07-07) eve / Passport と Better Auth の agent identity(Agent Auth プラグイン)が統合されていく⽅向が読み取れる — 具 体形は今後の発表を待つ。 ② Ship London(2026-06-17)で OSS エージェントフレームワーク eve (Apache-2.0‧"Next.js for agents")+ Vercel Passport (エージェント OIDC identity)+ Vercel Connect(OAuth トークン管理)を発表 ③ エージェント発デプロイは6か⽉で 3%未満 → 半数超(2026-06 時点) これから
  46. 10 — おわりに 01 TS で作るなら Better Auth — 型安全‧データ所有‧プラグイン網羅。

    02 Auth.js 合流と Vercel 買収で、エコシステムの中⼼に。 03 次の戦場は agent identity — その最前列に Better Auth がいる。
  47. 10 — 会社紹介 エネルギーの未来をつくる CHANGING ENERGY FOR A BETTER WORLD

    エンジニア採⽤中 詳細はエンジニア採⽤サイトもご覧ください! “エネチェンジ エンジニア” で検索🔍 カジュアル⾯談申込 エンジニア採⽤サイト
  48. 10 — 参考文献 参考⽂献 — ⼀次情報 Better Auth / Vercel

    エージェント認証 / その他 better-auth.com/blog/seed-round agentauthprotocol.com agent-auth.directory better-auth.com/blog/authjs-joins-better-auth github.com/better-auth/agent-auth-protocol better-auth.com/blog/better-auth-joins-vercel workos.com/auth-md github.com/workos/auth.md vercel.com/blog/vercel-acquires-better-auth datatracker.ietf.org vercel.com/blog/introducing-eve (draft-ietf-oauth-identity-assertion-authz-grant) github.com/better-auth/better-auth/releases/tag/v1.0.0 github.com/nextauthjs/next-auth/discussions/13252 ycombinator.com/companies/better-auth github.com/lucia-auth/lucia/discussions/1714 better-auth.com/docs/comparison techcrunch.com/2025/06/25/this-self-taught-ethiopian-dev-b better-auth.com/docs/ai-resources better-auth.com/llms.txt uilt-an-authentication-tool-and-got-into-yc workos.com/blog/vercel-acquires-better-auth-migrate-to-wor kos AI 利⽤統計(§9-00) radar.cloudflare.com(bot 57.5%・2026-06)/ salesforce.com/news(Cyber Week AI 関与 20%・2025-12)/ business.adobe.com(AI 経由流入 +393%・2026 Q1)/ anthropic.com(MCP サーバー1万超・2025-12)/ gartner.com(B2B 購買 90% 予測・2025-11) ご清聴ありがとうございました。#Offers_DeepDive @cu30rry_ / ENECHANGE株式会社
  49. APPENDIX Full Reference 詳細リファレンス Appendix 歴史の各論 / コア機構‧認証⽅式‧統合‧プラグイン‧Infrastructure の全詳細 /

    競合⽐較の各論 / AI が認証を「書く」開発体験 ※ 最新情報や正確な情報は公式ドキュメントを参照してください
  50. 02 — 歴史 誕⽣ — 独学の開発者が寝室から作った OSS エチオピア‧アディスアベバ出⾝の独学プログラマー Bereket Engida

    を中⼼に、2024年、⾃宅の寝室で開発が 始まった。 正確に⾔うと: 「6か⽉」は開発期間ではなく、公開後に ⼈気化するまでの期間。 2024年9⽉の GitHub 公開から わずか半年で⼈気ライブラ 創業者数: 単独説(TechCrunch/YC)と共同説(Addis Insight)が併存するため断定しない。 リへ 成⻑。世界標準候補への道を駆け上がった。
  51. 02 — 歴史 買収の構図 — 認証レイヤーの垂直統合 VERCEL Next.js Auth.js(2025-09 保守移管)

    Better Auth(2026-07 買収) React エコシステムの認証中核を掌握 。フレームワー クと認証が同⼀ベンダーに揃った。 WorkOS は即⽇「Better Auth ユーザーは WorkOS へ」と応 戦ブログを公開 — 業界が警戒している証拠。
  52. 02 — 歴史 OSS 認証ライブラリの明暗 — Lucia と Better Auth

    OBITUARY FRONT PAGE Lucia RIP Better Auth 2025-03、v3 を⾮推奨化し開発停⽌。 同じ⾃前ホスト思想から出発し、2年で Vercel 傘下へ駆け上 がった。 「⾃前実装のための学習リソース」へ転換した。 週間 470万+ DL の⽣態系を築いた。 ↘ ↗ 教訓: 思想だけでは⽣き残れない。エコシステム‧型安全‧網羅性‧保守の持続性が分⽔嶺。
  53. APPENDIX 03 Core Concepts コア機構 auth インスタンス / API /

    CLI / Client / Database / Hooks / Session / Rate limit
  54. 03 — コア機構 全体像 — コア+プラグインの⼆層構造 Plugins 層(任意‧着脱可) twoFactor /

    organization / genericOAuth / passkey … endpoints‧schema‧hooks‧rateLimit を「⾜す」 Core 層(常に存在) emailAndPassword‧socialProviders‧session‧cookies‧rateLimit‧user/a ccount‧email Database アダプタ Kysely(組込)/ Prisma / Drizzle / MongoDB ↓ auth.handler を /api/auth/* にマウント Client — createAuthClient 対のクライアントプラグインとともに叩く: signIn / useSession / twoFactor.* … -/ auth.ts — 出発点 import { betterAuth } from "better-auth"; export const auth = betterAuth({ emailAndPassword: { enabled: true }, socialProviders: { google: { clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret : process.env.GOOGLE_CLIENT_SECRET!, }, }, });
  55. 03 — コア機構 auth インスタンスの 4つの顔 auth.handler auth.api Web 標準の

    (req) -> Promise<Response> ハンドラ。/api/auth/* を処理す 全エンドポイントをサーバー側から型安全に呼ぶための関数群。 る。 auth.$Infer auth.options Session / User などの型を推論するための型専用名前空間。 正規化済みの設定オブジェクト。
  56. 03 — コア機構 API — すべての機能はエンドポイント、呼び⽅は2経路 経路1 HTTP 経由 —

    auth.handler をマウントし、クラ イアントから叩く 経路2 サーバー内部から auth.api.* を関数として直接呼 ぶ(HTTP ⾮経由で⾼速) -/ サーバー側でセッション取得 const session = await auth.api.getSession({ headers: await headers(), }); auth.api は { body, headers, query, params } を取り、戻り 値は 既定でパース済みデータ(Response ではない)。 -/ サインアップも内部呼び出しできる const res = await auth.api.signUpEmail({ body: { email: "[email protected]", password: "password1234", name: "Taro" , }); },
  57. 03 — コア機構 ⽣の Response / ヘッダが欲しいとき asResponse: true —

    ⽣の Response を返す returnHeaders: true — Set-Cookie 等を取り出す const response = await auth.api.signInEmail({ body: { const { headers, response } = await email, password }, asResponse: true , }); auth.api.signInEmail({ body: { email, password }, returnHeaders: true , }); const sc-camel-set-cookie = headers.get( "set-cookie" );
  58. 03 — コア機構 route handler への接続 — catch-all に1本 basePath

    の既定は /api/auth Next.js App Router -/ app/api/auth/[--.all]/route.ts Node / Express import { toNodeHandler } from "better-auth/node" ; import { toNextJsHandler } from "better-auth/next-js" ; app.all("/api/auth-*", toNodeHandler(auth)); -/ 注意: express.json() より前にマウント -/ (body を奪わ export const { GET, POST } = toNextJsHandler(auth.handler); れないため)
  59. 03 — コア機構 エラーハンドリングの⾮対称性 auth.api.* authClient.* 失敗時に APIError を throw

    throw せず { data, error } を返す サーバー内部呼び出しは try/catch で受ける。 error.code で分岐する Result 型スタイル。 この⾮対称を必ず押さえる。
  60. 03 — コア機構 CLI — generate / migrate / init

    / secret(+ info / mcp) generate アダプタに応じたスキーマ/マイグレーションを⽣成 # スキーマ生成(ORM は各自のツールで適用) npx @better-auth/cli@latest generate migrate DB に直接適⽤(Kysely 組み込みアダプタ限定) init 初期セットアップ # Kysely 組み込みのみ DB 直接適用 secret BETTER_AUTH_SECRET ⽤キー⽣成 npx @better-auth/cli@latest init info 環境‧設定の診断情報(issue 報告⽤) mcp エディタ向け MCP サーバー設定を書き出し 外部 ORM(Prisma / Drizzle / MongoDB)は migrate 不可 → generate 後に ORM ⾃⾝のマイグレーションツールで適⽤。 npx @better-auth/cli@latest migrate npx @better-auth/cli@latest secret # エディタ AI に文脈を渡す npx @better-auth/cli mcp --cursor
  61. 03 — コア機構 Client — インポートパスでフレームワークを切り替える better-auth/react React(useSession は hook)

    better-auth/vue Vue(リアクティブな ref / store) better-auth/svelte Svelte(store) better-auth/solid Solid(signal) better-auth/client フレームワーク⾮依存(vanilla) -/ lib/auth-client.ts (React) import { createAuthClient } from "better-auth/react"; export const sc-camel-auth-client = createAuthClient({ baseURL: "http:-/localhost:3000" , });
  62. 03 — コア機構 主要なクライアントメソッド -/ サインアップ(email/password)。email・password・name が必須 const { data,

    error } = await authClient.signUp.email( { email: "[email protected]", password: "password", name: "User" , } ); -/ サインイン(email/password) await authClient.signIn.email({ email, password }); -/ ソーシャルサインイン(OAuth リダイレクト開始) await authClient.signIn.social({ provider: "google", callbackURL: "/dashboard" }); -/ サインアウト await authClient.signOut(); throw せず { data, error } を返す — error.code で分岐。
  63. 03 — コア機構 セッションの参照 — useSession と getSession useSession —

    リアクティブに購読 export function UserButton() { const { data : session, isPending, error } = const { data: session } = await authClient.getSession(); authClient.useSession(); if (isPending) return <span>--.-/span>; return } getSession — ⼀度だけ取得 <span>{session-.user.name}-/span>; React では hook、Vue / Svelte / Solid では各フレームワークのリアク ティブ‧プリミティブを返す。
  64. 03 — コア機構 セッションの失効 API — 複数デバイス管理 -/ アクティブなセッション一覧 const

    { data: sessions } = await authClient.listSessions(); -/ 特定のセッションを失効(token を指定) await authClient.revokeSession({ token : sessions[0].token 1台だけ失効 revokeSession({ token }) }); -/ 現在のセッション以外をすべて失効 await authClient.revokeOtherSessions(); -/ すべてのセッションを失効 await authClient.revokeSessions(); 現在以外を全部失効 revokeOtherSessions() 全部失効 revokeSessions()
  65. 03 — コア機構 Database — コアスキーマとアダプタ2⽅式 user session account verification

    ① 組み込み Kysely — ドライバ直結(migrate 可) import { Pool } from "pg"; ← 既定4モデル。プラグインが独⾃モデルを追加する ② ORM アダプタ — generate で出⼒ import { prismaAdapter } from "better-auth/adapters/prisma" ; export const auth = betterAuth({ database: new Pool({ connectionString : process.env.DATABASE_URL, }), }); const prisma = new PrismaClient(); export const auth = betterAuth({ database: prismaAdapter(prisma, { provider: "postgresql" , }), });
  66. 03 — コア機構 Database 詳解 — 内部は Kysely 「Kysely が対応する

    DB はそのまま動く」— ⽅⾔差は Better Auth 側が吸収する。 サーバーレス Neon / AWS RDS Data API エッジ Cloudflare D1 / Turso ⼤規模 MySQL PlanetScale(Vitess‧無停⽌スキーマ変更) エンタープライズ MS SQL(tedious + tarn で MssqlDialect) 迷ったら PostgreSQL — 実績‧ドキュメントが最も厚い database: new Pool({ connectionString: "postgres:-/--." , }) ※ BigQuery / ClickHouse(OLAP)は認証ストアに⾮典型 — 分析⽤途のみ。主要 DB 20種 の詳細は docs 05-database 参照。 DB なしのステートレスセッション(JWT)構成も可能。
  67. 03 — コア機構 アダプタの選び分け — 4系統 アダプタ 性質 スキーマ管理 向いているケース

    組み込み Kysely ドライバ直結‧最軽量 CLI migrate で直接適⽤ ORM を⼊れたくない Drizzle 型安全‧軽量‧SQL 寄り generate 後は drizzle-kit 運⽤ 既に Drizzle 採⽤ Prisma スキーマ駆動‧ツール充実 generate で Prisma スキーマ⽣成(Prisma 7+ 既に Prisma 採⽤ / 広範な DB は output パス必須) MongoDB NoSQL ドキュメント スキーマレス(migrate/generate 不要)。 join は 1.4.0+ experimental.joins: true drizzleAdapter(db, { provider: "sqlite", schema: { --.schema, user : schema.users }, }) -/ usePlural: true も可 プラグイン追加‧変更のたびに migrate / generate を再実⾏。 ドキュメント指向 / 既存 Mongo const db = client.db(); mongodbAdapter(db)
  68. 03 — コア機構 modelName の罠 — テーブル名ではない modelNameは「アダプタが解決するモデル名 」。Prisma では

    Prisma モデル名にマップされ、実テーブル名は @@map など ORM 側の責務。Kysely 直結時のみ実テーブル名と⼀致する。 export const auth = betterAuth({ user: { -/ アダプタのモデル名 modelName: "users", fields: { -/ カラム名のリネーム name: "full_name", email: "email_address" , }, }, session: { modelName: "user_sessions", fields: { userId: "user_id" }, }, }); 設定 — modelName: "users" ↓ アダプタのモデル名(Prisma ならモデル名) ↓ 物理テーブル名(@@map 等 ORM の責務)
  69. 03 — コア機構 User 設定 — additionalFields / changeEmail /

    deleteUser user: { additionalFields: { role: { type: ["user", "admin"], defaultValue: "user", -/ クライアントから渡させない input: false , }, lang: { type: "string", defaultValue: "en" }, }, changeEmail: { -/ 既定は無効 enabled: true, sendChangeEmailVerification: async ({ user, newEmail, url }) -> { --. }, }, deleteUser: { enabled: true, sendDeleteAccountVerification: async ({ user, url }) -> { --. }, }, } additionalFields type / required / defaultValue / input でスキーマ拡張。input: false は role 等「登録時にユーザー⼊⼒させない」フィールド に。 changeEmail 既定で無効。検証メールを送って変更を確定。 deleteUser 検証付き退会フロー → authClient.deleteUser({ token }) で確 定。
  70. 03 — コア機構 型安全 — $Infer とクライアントへの型ブリッジ クライアント: inferAdditionalFields サーバー:

    auth.$Infer import { inferAdditionalFields } from "better-auth/client/plugins"; type Session = typeof auth.$Infer.Session; -/ additionalFields も 自動反映 -/ Session["user"]["role"] が型に乗 る → 型ブリッジ import type { auth } from "~/auth"; export const sc-camel-auth-client = createAuthClient({ plugins: [inferAdditionalFields<typeof }); 別リポジトリなら inferAdditionalFields({ user: {--.} }) でフィールド定義を⼿渡しする。 auth>()],
  71. 03 — コア機構 Email / Mail — 設定の置き場所が違う 送信⼿段はユーザー実装。Better Auth

    は「いつ‧どんな URL / トークンで送るか」を組み⽴てて渡す。 メール検証 = emailVerification emailVerification: { sendOnSignUp: true, sendOnSignIn: true, autoSignInAfterVerification: true, sendVerificationEmail: async ({ user, url, token }) -> { await sendMail({ to: user.email, body : url }); }, afterEmailVerification: async (user) -> { -* 副作用 -/ }, } 検証と リセットで設定の置き場所が違う点に注意。 パスワードリセット = emailAndPassword emailAndPassword: { enabled: true, revokeSessionsOnPasswordReset: true, sendResetPassword: async ({ user, url, token }) -> { await sendMail({ to: user.email, body : url }); } },
  72. 03 — コア機構 Plugins — サーバーとクライアントの「対」構造 クライアント側 — better-auth/client/plugins サーバー側

    — better-auth/plugins import { twoFactorClient } from "better-auth/client/plugins"; import { twoFactor } from "better-auth/plugins"; export const auth = betterAuth({ plugins : [twoFactor()], }); ⇄ export const sc-camel-auth-client = ペア }); -/ → authClient.twoFactor.* が型安全に生える createAuthClient({ plugins : [twoFactorClient()], endpoints‧schema‧hooks‧rateLimit ルールを追加 対応アクション‧ストアを authClient に追加 サーバーに⾜したらクライアントにも⾜す。専⽤パス import でツリーシェイク。
  73. 03 — コア機構 OAuth — 2つの経路 ① socialProviders(組み込み) ② genericOAuth

    プラグイン 主要プロバイダは clientId / clientSecret を渡すだけ。 組み込みにないプロバイダはエンドポイントを⼿動指定して 接続(社内 IdP‧Keycloak 等)。 socialProviders: { google: { clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret : process.env.GOOGLE_CLIENT_SECRET!, }, } → 詳細は第4章で。
  74. 03 — コア機構 account linking — アカウント連携は既定で有効 account: { accountLinking:

    { enabled: true, 1⼈の user に複数の account(認証⽅式‧プロバイダ)が紐 付く。プロバイダが email verified を返せば既存ユーザーに 別プロバイダを紐付けられる。 trustedProviders: ["google", "github"], allowDifferentEmails: true , }, } allowDifferentEmails: true は「別 email を返すプロバ イダ」も連携対象にする — 乗っ取りリスクとのトレードオフ 。
  75. 03 — コア機構 Cookies — 署名と cookieCache の3⽅式 すべての Cookie

    はsecretで署名される。 session.cookieCache でセッションを Cookie 側にキャッ シュし、毎回の DB アクセスを削減。 compact 既定。コンパクトな署名付き表現 jwt JWT 形式 jwe 暗号化された JWE 形式 session: { cookieCache: { enabled: true, -/ 5分キャッシュ maxAge: 5 * 60, strategy: "compact" , }, }
  76. 03 — コア機構 Cookies — セキュア属性とドメイン共有 advanced: { -/ 本番では既定で有効

    useSecureCookies useSecureCookies: true, Secure 属性で HTTPS 限定。本番では既定で有効。 crossSubDomainCookies: { enabled: true, domain: "example.com" , }, cookiePrefix: "my-app" , } crossSubDomainCookies app.example.com と auth.example.com でセッション Cookie を共有。 cookiePrefix / advanced.cookies Cookie 名や個別属性(sameSite 等)をカスタマイズ。
  77. 03 — コア機構 Hooks① エンドポイント hooks(before / after) before →

    本処理 → after 各1つの createAuthMiddleware を受け、ctx.path で分岐 -/ before: body 書き換え・中断 before: createAuthMiddleware(async (ctx) -> { if (ctx.path --= "/sign-up/email") { if (!ctx.body-.email.endsWith("@example.com")) { throw new APIError("BAD_REQUEST" ,{ message: "社内メールのみ許可" }); } return { context: { --.ctx, body: { --.ctx.body, name: "Default" } } }; } }), -/ after: レスポンス後の副作用 after: createAuthMiddleware(async (ctx) -> { if (ctx.path.startsWith("/sign-in")) { const session = ctx.context.returned; -/ 監査ログ送信など } }), -/ ctx.context.session = 現在のセッション -/ before の書き換えは後段に伝播する
  78. 03 — コア機構 Hooks② databaseHooks — DB レコードに割り込む databaseHooks: {

    user: { create: { before: async (user, ctx) -> { if (user.isAgreedToTerms --= false) { throw new APIError("BAD_REQUEST" ,{ message: "規約同意が必要です" }); } } return { data: { --.user, role: "user" }, after: async (user, ctx) -> { -/ ウェルカムメール等の副作用 }, }, }, } }; user / session / accountのcreate / update ×before / afterをフック。 before が false → 操作を中断。{ data } → ペイロードを差し替 え。after = 成功後の副作⽤。
  79. 03 — コア機構 Session — 有効期限とローリング更新 session: { -/ 7日

    expiresIn: 60 * 60 * 24 * 7, -/ 1日ごとに延長 利⽤なし 7⽇で失効 updateAge: 60 * 60 * 24 , } 利⽤あり(ローリング) 失効線が先へスライド セッションが使われ、かつ updateAge(既定1⽇)に達すると、失 効時刻が「現在 + expiresIn」へ更新される。
  80. 03 — コア機構 Session — secondaryStorage と保存先の分岐 -/ Redis 等に逃がす3関数

    secondaryStorage: { get: async (key) -> await redis.get(key), set: async (key, value, ttl) -> await redis.set(key, value, "EX", ttl), delete: async (key) -> await redis.del(key), secondaryStorage あり? } Yes → Redis / KV に保存(storeSessionInDatabase: true で主 DB 併 存) / No → 主 DB の session テーブル -/ 主 DB なし + 短命 Cookie キャッシュ運用 cookieCache 有効? session: { cookieCache: { Yes → 署名/暗号化して Cookie にキャッシュ = ほぼ stateless / No → 毎回保存先を参照 maxAge: 5 * 60, refreshCache: false }, } 完全ステートレスは即時 revoke が効きにくいトレードオフ。
  81. 03 — コア機構 Rate limit — customRules と storage rateLimit:

    { -/ 本番モードでは既定で有効 enabled: true, -/ 秒 window: 60, -/ window 内の最大リクエスト数 max: 100, storage: "secondary-storage", storage の3択 memory(既定)/ database / secondary-storage。サーバーレ ス‧複数インスタンスでは memory はカウンタが分裂する。 customRules: { "/sign-in/email": { window: 10, max: 3 }, customRules "/two-factor-*": async パス単位で { window, max } を上書き。関数で動的算出も可。 }),}, } (request) -> ({ window: 10, max: 3 プラグインも独⾃ルールを持つ 例: twoFactor は /two-factor/* に専⽤のレート制限。
  82. 04 — 認証方式 Email & Password — enabled: true だけ

    DB アダプタさえあれば追加要件なし。signUp / signIn のエンドポイントが即有効になる。 auth.ts auth-client.ts import { betterAuth } from "better-auth"; export import { createAuthClient } from "better-auth/client" ; const auth = betterAuth({ emailAndPassword: { enabled: true , }, }); export const sc-camel-auth-client = createAuthClient({ baseURL: "http:-/localhost:3000" , });
  83. 04 — 認証方式 サインアップ / サインインのコード例 -/ name / email

    / password は必須 const { data, error } = await authClient.signIn.email({ email: const { data, error } = await "[email protected]", password: "password1234", authClient.signUp.email({ name: "John Doe", email: -/ 既定 true rememberMe: true, "[email protected]", password: "password1234", callbackURL: "/dashboard" , }); -/ 任意 image: "https:-/example.com/image.png", -/ 任意 callbackURL: "https:-/example.com/callback" , }); rememberMe: false でブラウザを閉じた時点でセッション失効。戻り値 は { data, error }(Result 型的)。
  84. 04 — 認証方式 emailAndPassword — 主な設定オプション オプション 既定値 説明 enabled

    false Email & Password 認証を有効化 disableSignUp false サインアップのみ無効化(招待制で利⽤) minPasswordLength 8 パスワードの最⼩⽂字数 requireEmailVerification false メール未検証ユーザーのサインインをブロック revokeSessionsOnPasswordReset false パスワードリセット時に全セッション失効 他: maxPasswordLength / autoSignIn / sendResetPassword / onPasswordReset / resetPasswordTokenExpiresIn / password(hash 差し替え)→ docs 参照
  85. 04 — 認証方式 メール検証 emailVerification: { sendVerificationEmail: async ({ user,

    url, token }) -> { void sendEmail({ to: user.email, subject: "メールアドレスを確認し てください", text: `確認リンク: ${url}` ,});}, -/ サインアップ時に自動送信 sendOnSignUp: true , }, emailAndPassword: { enabled: true, -/ 未検証は不可 requireEmailVerification: true , }, -/ 検証メールを再送 await authClient.sendVerificationEmail({ email: "[email protected]", callbackURL: "/" , }); -/ トークンで明示的に検証 await authClient.verifyEmail({ query: { token: "--." }, });
  86. 04 — 認証方式 列挙攻撃(user enumeration)対策 未登録メールで サインアップ 登録済みメールで サインアップ →

    → 200 200 OWASP 認証ベストプラクティス準拠 requireEmailVerification 有効時、または autoSignIn: false の とき発動。攻撃者が登録済みアドレスを推測できない。 既存ユーザーの再サインアップを検知したい場合は onExistingUserSignUp コールバック。 どちらでも同⼀の 200 を返す
  87. 04 — 認証方式 パスワードリセット — 3ステップ 1 サーバー: 送信処理を実装 emailAndPassword:

    { enabled: true, revokeSessionsOnPasswordReset: true, sendResetPassword: async ({ user, url, token }) -> { void sendEmail({ to: user.email, text: `再設定: ${url}` }); }, onPasswordReset: async ({ user }) -> { -/ 監査ログ・通知 }, } 2 クライアント: リセット要求 const { data, error } = await authClient.requestPasswordReset({ email: "[email protected]", redirectTo: "https:-/example.com/reset-passwor d" , }); -/ 旧 forgetPassword は非推奨 3 リンク先: 新パスワード設定 const { data: reset, error : resetError } = await authClient.resetPassword({ newPassword: "password1234", -/ URL クエリから取得 token, });
  88. 04 — 認証方式 パスワードポリシー emailAndPassword: { enabled: true, -/ 既定

    8 ⻑さは minPasswordLength / maxPasswordLength で設定。 minPasswordLength: 12, -/ 既定 128 maxPasswordLength: 256 , } ⽂字種の必須化(記号‧数字など)はコアに含まれない — Valibot 等の境界バリデーションか before フックで実装する。
  89. 04 — 認証方式 ハッシュ⽅式のカスタム — scrypt → Argon2id 既定は scrypt(メモリハード、Node.js

    ネイティブ実装あり)。hash / verify の差し替えで任意アルゴリズムに。 -/ password.ts — @node-rs/argon2 const opts: Options = { -/ 64 MiB memoryCost: 65536, timeCost: 3, parallelism: 4, outputLen: 32, -/ Argon2id algorithm: 2 , }; export async function hashPassword(password) { return await hash(password, opts); } export async function verifyPassword({ password, hash }) { return await verify(hash, password, opts); } emailAndPassword: { enabled: true, password: { hash: hashPassword, verify : verifyPassword, }, } verify は { password, hash } → boolean。引数の形が hash 関数 と異なる点に注意。
  90. 04 — 認証方式 OAuth 設定例 — Google / LINE socialProviders:

    { google: { clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, -/ 任意 prompt: "select_account" , }, line: { clientId: process.env.LINE_CLIENT_ID, clientSecret: process.env.LINE_CLIENT_SECRET, -/ scope: ["custom"], -/ disableDefaultScope: true, }, } LINE Developers Console — 事前設定4ステップ 1 チャネルを作成 2 Channel ID / Channel secret を控える 3 Redirect URI を登録 — ローカルは http:-/localhost:3000/api/auth/callback/line 4 スコープ有効化 — 最低 openid、名前‧アバター‧メールは profile / email を追加
  91. 04 — 認証方式 signIn.social と ID トークンサインイン await authClient.signIn.social({ -/

    "google" など provider: "line", callbackURL: "/dashboard", errorCallbackURL: "/error", -/ 新規のみ newUserCallbackURL: "/welcome" , }); 複数クライアント ID の受理 Web iOS Android → 単⼀バックエンド Google / Apple / Microsoft Entra / Facebook / Cognito は clientId に配列 を渡すと複数クライアント ID を受理 — ネイティブ SDK の トークンをクロスプラットフォームで検証できる。
  92. 04 — 認証方式 対応プロバイダ⼀覧 — 地域選好まで組み込み 主要 ID 基盤 Google

    / Apple / Microsoft / Facebook ⽇本‧アジア‧ロシア向け LINE / Kakao(Kakao Talkの運営元) / Naver(韓国最⼤の検索エンジン) / VK(ロシアのSNSアプリ) 開発者 / コード GitHub / GitLab / Hugging Face(AI‧機械学習版のGitHub) チャット / コミュニティ Discord / Slack / Twitch / Reddit / Kick(ライビ配信プラットフォーム) ⽣産性 / SaaS Notion / Atlassian / Linear / Figma / Dropbox / Salesforce / Vercel / Zoom / LinkedIn メディア / ソーシャル Twitter/X / TikTok / Spotify / Roblox クラウド ID Amazon Cognito
  93. 04 — 認証方式 Generic OAuth — OAuth 2.0 / OIDC

    なら何でも接続 社内 IdP、Auth0 / Keycloak / Okta、Instagram / Coinbase 等の独⾃ OAuth もこれで扱う。 import { genericOAuth } from "better-auth/plugins"; plugins : [ genericOAuth({ config: [{ providerId: "custom-oauth", clientId: process.env.CUSTOM_CLIENT_ID, clientSecret: process.env.CUSTOM_CLIENT_SECRET, authorizationUrl: "https:-/auth.example.com/authorize", tokenUrl: "https:-/auth.example.com/token", issuer: "https:-/auth.example.com", scopes: ["openid", "profile", "email" ], }], }), ] -/ クライアント側の対プラグイン plugins: [genericOAuthClient()] -/ サインインは providerId を渡す await authClient.signIn.oauth2({ providerId: "custom-oauth", callbackURL: "/dashboard" , }); 組み込み⽤の provider とは別 — Generic OAuth は providerId を渡す signIn.oauth2。
  94. 04 — 認証方式 プリセットヘルパー — URL ⼿書き不要 import { genericOAuth,

    slack } from "better-auth/plugins"; plugins : [ genericOAuth({ auth0 keycloak microsoftEntraId config : [ okta slack slack({ clientId: process.env.SLACK_CLIENT_ID, hubspot clientSecret : process.env.SLACK_CLIENT_SECRET, line patreon ], }), ] }),
  95. 04 — 認証方式 ⼿動設定 と OIDC discoveryUrl ⾃動設定 Instagram(⼿動) {

    providerId: "instagram", clientId: --., clientSecret: --., authorizationUrl: "https:-/api.instagram.com/oauth/au thorize" , tokenUrl: "https:-/api.instagram.com/oauth/ac cess_token" , scopes: ["user_profile","user_media" ], } Coinbase(⼿動) { providerId: "coinbase", clientId: --., clientSecret: --., authorizationUrl: "https:-/www.coinbase.com/oauth/aut horize" , tokenUrl: "https:-/api.coinbase.com/oauth/tok en" , scopes: ["wallet:user:read" ], } OIDC は discoveryUrl だけ { providerId: "my-provider", discoveryUrl: "https:-/auth.example.com/.well-kno wn/openid-configuration" , clientId: "--.", clientSecret: "--." , } -/ authorizationUrl / tokenUrl / -/ userInfoUrl / issuer を自動取得
  96. 04 — 認証方式 GenericOAuthConfig — 設定オプション フィールド 説明 providerId プロバイダ識別⼦(必須)。signIn.oauth2

    の providerId と⼀致させる clientId / clientSecret OAuth クライアント ID / シークレット(必須) discoveryUrl OIDC/OAuth 設定の⾃動取得 URL。各エンドポイントを補完 scopes 要求するスコープ pkce PKCE を有効化するか 他: issuer / requireIssuerValidation / authorizationUrl / tokenUrl / userInfoUrl / redirectURI / responseType / prompt / accessType / accessTokenExpiresIn / getUserInfo → docs 参照 ※ magic link / Email OTP / username / phone / anonymous は認証系プラグイン → 第6章で扱う。
  97. 05 — フレームワーク統合 思想 — route handler を差し込むだけ Request →

    auth.handler コアの正体はWeb Fetch 標準の単⼀関数 。統合 = catch-all ルート 1本に auth.handler を渡すだけ。Request → Response を扱える⼟ 台なら Deno / Bun / Cloudflare Workers でも動く。 → Promise<Response> 公式ヘルパ(toNextJsHandler / toNodeHandler)は型の橋渡 しをする糖⾐にすぎない — 無くても直接呼べる。
  98. 05 — フレームワーク統合 対応⼀覧① フロント / フルスタック — すべて公式 フレームワーク

    差し込み⼝(catch-all) ハンドラ Next.js app/api/auth/[--.all]/route.ts toNextJsHandler(auth) Nuxt server/api/auth/[--.all].ts auth.handler(toWebRequest(event)) SvelteKit src/hooks.server.ts svelteKitHandler({--.}) SolidStart routes/api/auth-*all.ts toSolidStartHandler(auth) Astro pages/api/auth/[--.all].ts auth.handler(ctx.request) React Router v7 / Remix app/routes/api.auth.$.ts(resource route) loader / action で auth.handler TanStack Start src/routes/api/auth/$.ts auth.handler(request)
  99. 05 — フレームワーク統合 対応⼀覧② バックエンド フレームワーク 区分 差し込み⼝ / ハンドラ

    Hono 公式 app.on(["POST","GET"], "/api/auth-*") → auth.handler(c.req.raw) Fastify 公式 /api/auth-* catch-all → Node req を Request 変換後 auth.handler Express 公式 app.all("/api/auth-*splat") → toNodeHandler(auth) Elysia 公式 /api/auth-* を mount → auth.handler Nitro 公式 server/routes/api/auth/[--.all].ts → auth.handler(toWebRequest(event)) Convex 公式 @convex-dev/better-auth(公式コンポーネント) NestJS コミュニティ @thallesp/nestjs-better-auth — AuthModule + catch-all Encore コミュニティ raw endpoint の catch-all → auth.handler(request)
  100. 05 — フレームワーク統合 対応⼀覧③ モバイル / デスクトップ プラットフォーム 区分 クライアント側

    Expo 公式 @better-auth/expo expoClient({ scheme, storage }) Lynx 公式(ByteDance) createAuthClient Electron コミュニティ renderer から createAuthClient モバイルアプリ → 既存の auth.handler サーバを新設しない — 既存サーバをそのまま叩く。プラット フォーム差分は「Cookie の保存先」と「ディープリンクの scheme」に集約される。
  101. 05 — フレームワーク統合 代表コード例1 — Next.js app/api/auth/[...all]/route.ts サーバコンポーネント / Server

    Action import { auth } from "@/lib/auth"; import { auth } from "@/lib/auth"; import { toNextJsHandler } from import { headers } from "next/headers"; "better-auth/next-js"; const session = await auth.api.getSession({ headers: export const { POST, GET } = toNextJsHandler(auth); await headers(), });
  102. 05 — フレームワーク統合 代表コード例2 — Hono import { Hono }

    from "hono"; import { serve } from "@hono/node-server"; import { auth } from "./auth"; const app = new Hono(); catch-all ルートを1本切り、Web 標準の c.req.raw を 渡すだけ。 app.on(["POST", "GET"], "/api/auth-*", (c) -> { return auth.handler(c.req.raw); }); serve(app); 別オリジンから叩くなら cors ミドルウェアは認証ルート より前 に登録する(プリフライトを先に処理させる)。
  103. 05 — フレームワーク統合 代表コード例3 — Expo(2ステップ) 1 サーバー — expo()

    + trustedOrigins import { expo } from "@better-auth/expo"; export const auth = betterAuth({ plugins: [expo()], trustedOrigins: ["myapp:-/" ], }); 2 クライアント — Cookie を SecureStore に保存 import { expoClient } from "@better-auth/expo/client" ; import * as SecureStore from "expo-secure-store"; export const sc-camel-auth-client = createAuthClient({ baseURL: "http:-/localhost:8081", plugins : [ expoClient({ scheme: "myapp", storagePrefix: "myapp", storage : SecureStore, }), ], });
  104. 05 — フレームワーク統合 まとめ — 3例に共通する同⼀構造 Next.js Hono Expo toNextJsHandler(auth)

    auth.handler(c.req.raw) 既存の auth.handler を流用 常に「Request →auth.handler→ Response」。 新フレームワークが出ても、Web 標準を扱える限り統合は数⾏で済む。
  105. 06 — プラグイン大全 共通の注意 — 全プラグイン導⼊の3ステップ 1 サーバー plugins: [...]

    に追加 → 2 クライアントに対応プラグイン追加 → 3 スキーマ再⽣成‧マイグレーション 専⽤パス import: サーバー better-auth/plugins / クライアント better-auth/client/plugins 。個別サブパスは存在しない(例外は better-auth/plugins/access のみ)。 独⽴パッケージ組: Passkey @better-auth/passkey / Stripe @better-auth/stripe / SSO @better-auth/sso / Polar @polar-sh/better-auth / Dub @dub/better-auth npx @better-auth/cli generate npx @better-auth/cli migrate 追加‧変更のたびに再実⾏必須 — 忘れるとスキーマ不整合で実⾏時に 落ちる。
  106. 06 — プラグイン大全 / 認証系 認証系プラグイン 早⾒表(10種) プラグイン 役割 主な設定‧API

    Two-Factor (2FA) TOTP‧OTP‧バックアップコード‧信頼済みデバイス twoFactor() / twoFactorClient() Username メールに加えユーザー名でログイン username({ minUsernameLength }) Anonymous PII なしで認証済み体験 → 後から本アカウントへリンク(ゲスト→ 本登録) anonymous({ onLinkAccount }) Phone Number 電話番号 + SMS OTP(SMS 送信は⾃前) phoneNumber({ sendOTP }) Magic Link メールリンクでパスワードレス(送信は⾃前) magicLink({ sendMagicLink }) Email OTP メール OTP でサインイン/検証/リセット emailOTP({ sendVerificationOTP }) Passkey WebAuthn/FIDO2 パスワードレス passkey({ rpID, rpName, origin }) Generic OAuth 任意の OAuth2 / OIDC を追加(→ 第4章) genericOAuth({ config }) One Tap Google One Tap のワンタップログイン oneTap() / oneTapClient({ clientId }) SIWE Sign-In with Ethereum(ERC-4361) siwe({ domain, getNonce }) 薄い背景の5種 = 軽量‧補助枠(Username / Anonymous / Phone Number / Magic Link / One Tap)
  107. 06 — プラグイン大全 / 認証系 Two-Factor(2FA) TOTP‧メール/SMS OTP‧バックアップコード‧信頼済みデバイスを⼀括提供。ログイン後に第⼆要素検証フローを挿⼊する。 サインイン →

    チャレンジ(第⼆要素) → 検証 → セッション import { twoFactor } from "better-auth/plugins"; import { twoFactorClient } from "better-auth/client/plugins"; plugins : [ twoFactor({ -/ 認証アプリ上の表示名 twoFactorClient({ onTwoFactorRedirect() { issuer: "MyApp", -/ 検証ページへプログラム的に遷移 otpOptions: { async sendOTP({ user, otp }) { },}), -/ メール/SMS で otp を送信(自前) }, }), ] plugins : [ ]
  108. 06 — プラグイン大全 / 認証系 Email OTP — 1機構で3⽤途 import

    { emailOTP } from "better-auth/plugins"; plugins : [ emailOTP({ otpLength: 6, -/ 秒 expiresIn: 300, async sendVerificationOTP({ email, otp, type }) { -/ email 宛に otp を送信 }, emailOTP() ↓ type で分岐 "sign-in" サインイン }), ] "email-verification" メール検証 "forget-password" パスワードリセット await authClient.emailOtp.sendVerificationOtp({ email: "[email protected]", type: "sign-in" , });
  109. 06 — プラグイン大全 / 認証系 Passkey — WebAuthn / FIDO2

    ⽣体‧PIN‧セキュリティキーによるパスワードレス。フィッシング耐性。独⽴パッケージ @better-auth/passkey。 import { passkey } from "@better-auth/passkey"; plugins : [ passkey({ -/ ローカルは localhost rpID: "example.com", rpName: "My App", origin: "https:-/example.com" , }), ] -/ クライアントでパスキー登録 await authClient.passkey.addPasskey({ name: "Primary passkey" , }); 登録レーン addPasskey → デバイスの⽣体/PIN で鍵ペア⽣成 → 公開鍵 をサーバー保存 認証レーン チャレンジ署名をデバイス内の秘密鍵で実施 — パスワードが 存在しないためフィッシング不可
  110. 06 — プラグイン大全 / 認証系 SIWE — Sign-In with Ethereum(ERC-4361)

    ウォレット署名で認証。nonce ⽣成‧署名検証は⾃前実装(viem 推奨)— verifyMessage は署名復元のみ、nonce / ドメイン / Chain ID / 期限の 検証はプラグイン側。 import { siwe } from "better-auth/plugins"; plugins : [ siwe({ domain: "myapp.com", -/ メール紐付けユーザーを作成 anonymous: false, getNonce: async () -> generateSecureNonce(), verifyMessage: async ({ message, signature, address }) -> { return await verifySignature({ message, signature, address }); }, }), ] ウォレットが署名 ↓ 署名検証 + nonce/期限チェック ↓ セッション発⾏
  111. 06 — プラグイン大全 / 認可・承認系 認可‧承認系 早⾒表(5種) プラグイン 役割 主な設定‧API

    Admin ユーザー管理‧ロール付与‧BAN‧なりすまし admin({ adminRoles }) Agent Auth AI エージェント固有 identity‧登録‧discovery‧capability 認可(策定 中標準の実装、API 流動的 — 本番採⽤は慎重に) → 第9章で詳説 API Key API キーの発⾏‧管理‧検証。レート制限‧有効期限‧メタデータ apiKey() / verifyApiKey() MCP ⾃アプリを MCP クライアント向け OAuth プロバイダ化 mcp({ loginPage }) Organization 組織‧メンバー‧招待‧チーム‧RBAC のマルチテナント中核 organization({ ac, teams })
  112. 06 — プラグイン大全 / 認可・承認系 Admin — 管理ダッシュボードの⼟台 import {

    admin } from "better-auth/plugins"; plugins : [ admin({ adminRoles: ["admin", "superadmin"], adminUserIds: ["user_id_1"], impersonate(なりすまし) -/ 既定1時間 対象ユーザーのセッションを再現してデバッグ‧サポート対応。 なりすましセッションは既定1時間。 impersonationSessionDuration: 60 * 60, defaultBanReason: "規約違反" , }), BAN / 解除 ] banReason 付きで停⽌‧復帰を管理。 -/ クライアント 管理者の指定 await authClient.admin.impersonateUser({ userId: "user-id" adminRoles か adminUserIds で。 }); await authClient.admin.banUser({ userId: "user-id", banReason: "spam" });
  113. 06 — プラグイン大全 / 認可・承認系 API Key — プログラムアクセスの認証 import

    { apiKey } from "better-auth/plugins"; plugins : [ apiKey({ キー付きリクエスト rateLimit: { enabled: true, ↓ verifyApiKey maxRequests: 100 }, enableMetadata: true , }), ] -/ キー検証(権限チェック付き) const { valid } = await auth.api.verifyApiKey({ body: { key: "the_api_key", permissions: { files: ["read" ] } }, }); 許可 拒否 ビルトインのレート制限‧カスタム有効期限‧残回数制限‧メタ データ‧パーミッションに対応。
  114. 06 — プラグイン大全 / 認可・承認系 MCP — ⾃アプリを OAuth プロバイダ化

    MCP クライアント向けにアクセストークンを発⾏‧管理。withMcpAuth で MCP サーバを保護。別プロセス/別⾔語には Bearer リモート検証の 軽量 MCP Client。 import { mcp } from "better-auth/plugins"; plugins : [ mcp({ loginPage: "/sign-in", -/ 未認証クライアントの誘導先 MCP クライアント → ⾃アプリ → トークン発⾏‧保護 }), ] 近く OAuth Provider プラグインへ統合予定 (スキーマは OIDC Provider と共通)— 新規実装は移⾏先を意識する。
  115. 06 — プラグイン大全 / 認可・承認系 Organization — マルチテナントの中核 import {

    organization } from "better-auth/plugins"; import { ac } from "@/auth/permissions"; plugins : [ organization({ -/ 動的アクセス制御に必須 ac, teams: { enabled: true }, dynamicAccessControl: { enabled: true, maximumRolesPerOrganization: 10 , }, }), ] -/ クライアント側もペアで plugins: [organizationClient({ teams: { enabled: true } })] 組織(Organization) ↓ メンバー チーム 招待 RBAC ロール ac + dynamicAccessControl で実⾏時に組織ごとのカスタムロールを ⽣成できる。
  116. 06 — プラグイン大全 / 企業系 企業系 早⾒表 + OAuth Provider

    への合流 プラグイン 役割 OIDC Provider ⾃前の OpenID Connect プロバイダを構築(OAuth Provider へ移⾏予定) OAuth Provider OIDC Provider と MCP を束ねる後継統合プラグイン SSO 外部の SAML 2.0 / OIDC / OAuth2 を「消費」して SSO ロ グイン SCIM SCIM サーバを公開しディレクトリ同期‧⾃動プロビ ジョニング OIDC Provider MCP ↓ 合流 OAuth Provider(単⼀窓⼝へ)
  117. 06 — プラグイン大全 / 企業系 OIDC Provider — ⾃社をログイン基盤に import

    { oidcProvider } from "better-auth/plugins"; plugins : [ oidcProvider({ loginPage: "/sign-in", サードパーティアプリ → ⾃社 = OIDC プロバイダ consentPage: "/oauth/consent", getAdditionalUserInfoClaim: async (user, scopes, client) -> { return { role : user.role }; }, }), ] 認可コードフローでログインを提供。loginPage / consentPage は 差し替え可能、getAdditionalUserInfoClaim で UserInfo に独⾃ク レームを追加。
  118. 06 — プラグイン大全 / 企業系 SSO — 企業 IdP を「消費」する

    import { sso } from "@better-auth/sso"; plugins : [ sso({ organizationProvisioning: { disabled: false, defaultRole: "member" , }, }), ] 企業 IdP(Okta / Entra ID …) ↓ SAML 2.0 / OIDC / OAuth2 await auth.api.registerSSOProvider({ body: { providerId: "acme-corp", issuer: "https:-/acme.okta.com", domain: "acmecorp.com", organizationId: "org_acme_id", samlConfig: { -* メタデータ・証明書 -/ headers, }); SSO プラグイン(@better-auth/sso) ↓ 組織⾃動プロビジョニング‧ロール付与 } },
  119. 06 — プラグイン大全 / 企業系 SCIM — ディレクトリ同期を受け付ける 外部 IdP(Okta

    / Entra ID) → scim() ユーザー / グループの⾃動プロビジョニングを受け付 ける SCIM サーバを公開。属性は既定でコアフィール ドへ⾃動マッピング(カスタマイズ可)。 → 作成‧更新‧無効化を⾃動同期 scim() / auth.api.getSCIMResourceType() 。エン タープライズのディレクトリ同期要件で使う。
  120. 06 — プラグイン大全 / ユーティリティ ユーティリティ系 早⾒表(9種) プラグイン 役割 備考

    Bearer Token Cookie の代わりに Bearer トークンで API 認証 利⽤は慎重に(Cookie 推奨) Device Authorization OAuth 2.0 デバイス認可グラント(RFC 8628) CLI‧TV‧IoT 向け Have I Been Pwned 漏洩済みパスワードの利⽤を拒否 k-匿名性チェック i18n 認証エラーメッセージ等の多⾔語化 ⽂⾔ローカライズ Last Login Method 最後に使った認証⼿段を記録‧表⽰ 「前回は Google」表⽰ Multi-Session 同⼀ブラウザで複数アカウントの同時セッション(maximumSessions) アカウント切替 UX OAuth Proxy OAuth リクエストをプロキシ — redirect URL が確定しないプレビュー環境向け 開発時の救済 One-Time Token 単回使⽤トークンの⽣成‧検証 クロスドメイン受け渡し Test utilities 認証フローのテスト⽤ヘルパー E2E / 結合テストの⾜場
  121. 06 — プラグイン大全 / ユーティリティ Captcha — サインアップ / イン

    / リセットのボット対策 import { captcha } from "better-auth/plugins"; plugins : [ captcha({ -/ google-recaptcha | hcaptcha | captchafox provider: "cloudflare-turnstile", secretKey : process.env.TURNSTILE_SECRET_KEY!, }), ] フォーム送信 → チャレンジ検証 → 通過 / ブロック 対応: Cloudflare Turnstile / Google reCAPTCHA / hCaptcha / CaptchaFox。 endpoints で保護対象を上書き。reCAPTCHA v3 は minScore、hCaptcha / CaptchaFox は siteKey を追加指定。
  122. 06 — プラグイン大全 / ユーティリティ JWT — 外部サービス連携⽤のトークン発⾏ import {

    jwt } from "better-auth/plugins"; plugins : [ jwt({ jwks: { -/ ES256 / RSA256 / PS256 も可 keyPairConfig: { alg: "EdDSA" }, }, }), ] JWT 取得エンドポイント → 外部サービスが JWKS で検証 セッションの置き換えではない — JWT を要求する外部サービス連携向 け。検証⽤ JWKS エンドポイントも提供する。
  123. 06 — プラグイン大全 / ユーティリティ OpenAPI — 全エンドポイントをリファレンス化 import {

    openAPI } from "better-auth/plugins"; plugins : [ openAPI({ -/ UI の公開パス path: "/reference" , ] }), /reference — Scalar UI POST /sign-up/email POST /two-factor/verify-totp GET /organization/list コア + 全プラグインを OpenAPI 3.1.1 で出⼒。Scalar 製 UI でブラウズ‧実⾏テス ト。開発初期の動作確認 UI としても有⽤。
  124. 06 — プラグイン大全 / その他 Dub — リンク経由サインアップのリードトラッキング import {

    dubAnalytics } from "@dub/better-auth"; import { Dub } from "dub"; plugins : [dubAnalytics({ dubClient: new Dub(),}),] Dub リンク経由のサインアップを計測し、リードを追跡する。 決済ではなくグロース / アナリティクス⽤途。OAuth リンキングのサポー トも追加する。
  125. 06 — プラグイン大全 / その他 ⾃作プラグイン / コミュニティプラグイン -/ plugin.ts

    import type { BetterAuthPlugin } from "better-auth"; import { createAuthEndpoint, sessionMiddleware } from "better-auth/api"; export const sc-camel-my-plugin = () -> ({ id: "my-plugin", endpoints: { hello: createAuthEndpoint( "/my-plugin/hello" ,{ method: "POST", body: z.object({ name: z.string() }), use: [sessionMiddleware] }, async (ctx) -> ctx.json({ message: `hi ${ctx.body.name}` }), ), }, }) satisfies BetterAuthPlugin; ⾃作 satisfies BetterAuthPlugin なオブジェクトを返す関数。 createAuthEndpoint + sessionMiddleware / requireResourceOwnership。独⾃テーブルは schema 宣⾔ → CLI 再⽣成。 コミュニティ ⽤途特化の拡張が多数。公式⼀覧から探せる‧⾃作の登録も 可。
  126. 06 — プラグイン大全 / 決済 決済プラグイン群 (1/2) — 位置づけと3モデル Stripe

    / Polar は公式保守、Autumn / Dodo / Creem / Chargebee / Commet はベンダー保守(いずれも公式 docs にプラグインページあり)。 朱⾊ = MoR(税 /VAT を丸投げできるモデル)— 決済プラグイン選定の最⼤の分岐点。 ① 直接 PSP ② MoR(Merchant of Record) ③ 上乗せ層 Stripe Polar / Dodo / Creem / Commet Autumn / Chargebee createCustomerOnSignUp‧subscription (plans / freeTrial / limits / upgrade 差額課 ⾦)‧Webhook ⾃動処理。 販売者を肩代わり。Polar は開発者ファース ト MoR — GitHub 連携‧ベネフィット⾃動 付与、checkout / portal / usage / webhooks。 Autumn = Stripe 上の宣⾔的課⾦レイヤー (attach / check / track)。Chargebee = サ ブスク / レベニュー管理層。 税の最終責任 = ⾃社 stripe() / polar() / autumn() 税/VAT の登録‧計算‧申告‧納税を代 ⾏ 税の最終責任 = ⾃社
  127. 06 — プラグイン大全 / 決済 決済プラグイン群 (2/2) — 残る4種と選び⽅ Dodo

    Creem Chargebee Commet 150+カ国グローバル MoR。クレ ジット課⾦‧使⽤量メータリング 内蔵 税コンプラ込み MoR + レベ ニュースプリット内蔵 PSP の上のサブスク管理層 — プ ロレーション‧多通貨 ‧RevRec‧ダニング‧複数 PSP AI/API 課⾦⼀気通貫 MoR — portal / subscriptions / features / usage / seats 要件‧状況 推奨 税/VAT を丸投げ(MoR)したい Polar / Dodo / Creem / Commet 直接 PSP で最⼤の柔軟性 Stripe Stripe は残して AI/SaaS の従量‧クレジット Autumn グローバル販売(150+カ国)を最速で Dodo Payments 収益分配(レベニュースプリット)込み Creem エンタープライズの複雑サブスク‧収益認識 Chargebee AI 従量 + feature gating + seat を MoR で Commet dodopayments() / creem() / chargebee() / commet()
  128. 07 — Infrastructure 位置づけ — ライブラリが埋めない「運⽤」を肩代わり Dashboard Security ① ユーザー‧組織‧セッションを眺めて操作する管理画⾯

    ② クレデンシャルスタッフィングやボットの不正検知‧遮断 Email & SMS Enterprise ③ 検証‧リセット‧招待メールの確実な配信 コア(無料‧OSS‧⾃前ホスト) 外周 = Infrastructure(有料マネージド‧4本柱) ④ エンタープライズ向け SSO / SCIM / ログドレイン dash() / sentinel() の実体もプラグイン — 違いは接続先が有料マネージド である点だけ。
  129. 07 — Infrastructure 導⼊はプラグイン1⾏ 1 install → 2 env(API_KEY のみ必須)

    → 3 サーバー → 4 クライアント # npm install @better-auth/infra import { dashClient, sentinelClient } from # BETTER_AUTH_API_KEY=--. のみ必須 "@better-auth/infra/client"; import { dash, sentinel } from "@better-auth/infra"; plugins : [ plugins : [ dashClient(), dash({ apiKey : process.env.BETTER_AUTH_API_KEY }), sentinelClient({ autoSolveChallenge: true }), sentinel({ apiKey : process.env.BETTER_AUTH_API_KEY }), -/ sentinel は Pro 以上 -/ フィンガープリント + PoW 自動解決 ] ] Expo / RN は @better-auth/infra/native 。dash と sentinel は独⽴ 利⽤可、両⽅で全機能。
  130. 07 — Infrastructure アーキテクチャ — 観測‧判定‧配信だけを委譲する ⾃分のアプリ(⾃前ホスト) DB とユーザーデータは⾃前に残る クライアントは

    X-Visitor-Id を付与、PoW は X-PoW-Solution で再送 イベント送信(dash) → リクエスト検査(sentinel) ⇄ 管理 GUI(/dash/*) ← 監査ログ(/events/*) ⇄ Infra 障害でも認証フロー本体は⽌めない設計。判定は log / challenge / block。 Better Auth Infra(マネージド) 分析‧検知‧配信の「運⽤知能」のみ タイムアウト既定: API 3000ms / KV 1000ms
  131. 07 — Infrastructure / 4本柱① 柱①: Dashboard dash() dash({ apiKey:

    process.env.BETTER_AUTH_API_KEY, -/ 既定 apiTimeout: 3000, kvTimeout: 1000, activityTracking: { enabled: true, -/ 既定5分 updateInterval: 300000 , }, }) -/ lastActiveAt 列が追加される -/ → 有効化後マイグレー ション必須 ベストプラクティス: API キー必須 / トラッキング間隔は慎重に / ログ 保持はプラン依存 / エンドポイントは権限を適切に。 ⼊れるだけで有効になるもの イベント⾃動収集 ⼿動計装不要。全認証イベントを記録 管理 API 群 /dash/users‧/dash/user/ban‧/dash/user/impersonat e‧/dash/sessions‧/dash/session/revoke‧組織 / チー ム / 招待‧エンタープライズ‧2FA 分析 /dash/stats‧/dash/graph‧/dash/retention‧/dash/m ap 監査ログ照会 /events/list‧/events/audit-logs‧/events/types
  132. 07 — Infrastructure / 4本柱② 柱②: Security sentinel() — 包括的不正対策(Pro

    以上) リクエスト → 判定 → log(記録のみ) challenge(PoW‧難易度既定18) クレデンシャルスタッフィン グ 失敗しきい値→challenge→block (windowSeconds / cooldownSeconds) 不可能移動 maxSpeedKmh 超の地理移動を検知 トライアル悪⽤ フィンガープリント(maxAccountsPerVisitor) 漏洩パスワード HIBP k-匿名性 — フルパスワード⾮送信 休眠アカウント再活性化 staleDays(乗っ取り兆候の通知) その他 ジオブロック(allow/denyList)‧ボット‧不審 IP‧ベロシティ‧使い捨てメール遮断 (strictness: low/medium/high)‧メール正規化 (プラスタグ除去) block(遮断) sentinel({ security: { credentialStuffing: { enabled: true, thresholds: { challenge: 3, block: 5 }, windowSeconds: 3600, cooldownSeconds: 900 , }, impossibleTravel: { enabled: true, maxSpeedKmh: 1000, action: "challenge" , }, compromisedPassword: { enabled: true, action: "block" , }, challengeDifficulty: 18 , }, }) ベストプラクティス: まず log から → しきい値調整 → block より先に challenge。イベントは security_* として監査ログへ。
  133. 07 — Infrastructure / 4本柱③ 柱③: Email Service — マネージド配信(Pro

    以上) import { sendEmail } from "@better-auth/infra"; -/ 認証フローのコールバックから呼ぶだけ async sendResetPassword({ user, url }) { await sendEmail({ template: "reset-password", to: user.email, variables: { resetLink: url, userEmail: user.email, appName: "Your App" }, }); } -/ 戻り値 { success, messageId?, error? } 本番は送信を await しない (タイミング攻撃回避)。サーバーレスは waitUntil。 組み込みテンプレート13種 verify-email / reset-password / change-email / sign-in-otp / verify-email-otp / reset-password-otp / magic-link / two-factor / invitation / application-invite / delete-account / stale-account-user / stale-account-admin AWS SES SendGrid Resend
  134. 07 — Infrastructure / 4本柱④ 柱④: Enterprise — SSO /

    SCIM / ログドレイン SSO SCIM ログドレイン /dash/organization/sso-providers /directories /directory /log-drains /log-drain /sso-provider /directory/token /log-drain/test ディレクトリ同期‧⾃動プロビジョニング SIEM 転送で⻑期保管‧相関分析 /sso-provider/verify-domain 企業 IdP との SAML / OIDC 接続を組織単位 で管理 すべて dash() のエンドポイント群に統合。ダッシュボードはロールベースアクセス前提。
  135. 07 — Infrastructure Audit Logs — 発⽣ → 捕捉 →

    蓄積 → 照会 ユーザー / セッション系 組織系 セキュリティ系 user_signed_up / user_signed_in / session_created / user_impersonated / password_changed / account_linked / email_verification_sent … organization_created / member_added / member_role_updated / invite_accepted / team_created … security_blocked / security_credential_stuffing / security_impossible_travel …(sentinel 使⽤時) const logs = await authClient.dash.getAuditLogs({ session: session.data, limit: 50, offset: 0, -/ eventType / organizationId / userId / -/ identifier で絞り込み可 }); -/ イベント配列 -/ limit/offset ループで全件取得可 logs.data-.events; getAuditLogs ⾃ユーザーのイベント(organizationId で組織スコープに) getAllAuditLogs admin / owner 権限組織の全件(organization プラグイン必須) limit 最⼤100‧既定50 / offset 既定0
  136. 07 — Infrastructure 料⾦プラン構造(docs 記載ベース) Enterprise Pro + SSO /

    SCIM / ログドレイン + 監査ログ⻑期 保持 + sentinel(不正対策) + Email Service 無料 dash 基本(イベント収集‧管理 API) 価格: —(要公式確認) 価格: —(要公式確認) 価格: —(要公式確認) docs には「sentinel = Pro 以上」「Email = Pro 以上」「ログ保持 = プラン依存」の⾔及のみ。価格数値は登壇直前に公式で確認。
  137. 07 — Infrastructure / ビジネスモデル ビジネスモデル (1/2) — OSS コア

    + Infrastructure = Supabase 型 「認証ライブラリはタダ。じゃあ何で⾷ってる?」— 運⽤を売る。 OSS 普及 ① OSS コア(無料)で普及 型安全‧網羅性‧低学習コストでエコシステムを育てる。普及した OSS が販売チャネルになる。 ↓ 販売チャネル化 ↓ ② Infrastructure(有料)で収益化 ⾃前運⽤すると重い領域をマネージドで売る。 運⽤知能へ課⾦ 核は「コアは⾃前、運⽤知能だけ買う」分離 — 主権を⼿放さない。
  138. 07 — Infrastructure / ビジネスモデル ビジネスモデル (2/2) — Auth0 /

    Clerk との対⽐ 観点 Auth0 / Clerk(全部ホスト) Better Auth + Infrastructure 認証コア ベンダーがホスト ⾃前ホスト(OSS‧無料) ユーザーデータ ベンダー側 ⾃前 DB に所有 課⾦対象 認証そのもの(MAU 等) 運⽤知能(分析‧不正対策‧配信) 採⽤の起点 営業‧サインアップ OSS の普及 ロックイン 強い(移⾏が重い) 弱い(コアは⼿元、有料層は着脱式) ただし有料層に寄せすぎるとロックインの芽 — どこまで委ねるか設計段階で線引きする。
  139. 08 — 比較 / なぜ◯◯ではないのか なぜ Auth0 ではないのか 良い点 業界標準。エンタープライズでの実績は随⼀、Universal

    Login と機能網羅も◎。 でも データはベンダー側。MAU 従量(超過 $0.07/MAU)でスケール時に⾼額化。「全部ホスト」前提でカスタマイズはベンダー の枠内。 → Better Auth なら: データは⾃分の DB、コストは⾃分のインフラ次第。公式移⾏ガイドあり。
  140. 08 — 比較 / なぜ◯◯ではないのか なぜ Clerk ではないのか 良い点 プリビルト

    UI で導⼊最速。B2C の定番、React DX は業界随⼀。 でも セッションストア‧ユーザーレコード‧署名鍵を⾃分で所有できない。データ主権とスケール時のコストは構造的な課題。 → Better Auth なら: セッションも鍵もレコードも⼿元。UI は⾃作(ヘッドレス)と引き換えに主権を取る。
  141. 08 — 比較 / なぜ◯◯ではないのか なぜ WorkOS ではないのか 良い点 エンタープライズ

    SSO / SCIM の王者。auth.md などエージェント認証にも積極的(→ 第9章)。 でも B2B 特化でスタック委譲が前提。コンシューマ認証や⾃由なデータモデルは主戦場ではない。 → Better Auth なら: SSO / SCIM プラグイン + Infra Enterprise で同領域へ、コアは⾃前のまま。
  142. 08 — 比較 / なぜ◯◯ではないのか なぜ Kinde ではないのか 良い点 認証

    + 課⾦ + フィーチャーフラグの統合。無料枠(10.5K MAU)も優しい。 でも ロックイン構造は Clerk と同型 — データもフラグも課⾦状態もベンダー側。 → Better Auth なら: 課⾦統合も決済プラグイン(Stripe / Polar / Autumn…)で対抗できる(→ 6-22 / 6-23)。
  143. 08 — 比較 / なぜ◯◯ではないのか なぜ Supabase Auth ではないのか 良い点

    Supabase を使っているなら⾃然な選択。セルフホストも可能。 でも BaaS 前提(GoTrue)。Postgres / RLS と密結合で、認証だけを切り出して持ち運べない。 → Better Auth なら: Supabase を「ただの Postgres」として使いながら、認証ロジックは⾃分のコードに置ける。
  144. 08 — 比較 / なぜ◯◯ではないのか なぜ OpenAuth ではないのか 良い点 同じ

    OSS‧セルフホスト思想。標準準拠の OAuth / OIDC サーバとして堅実。 でも 「認証サーバを別に⽴てる」思想で、アプリ組み込み型ではない。2FA / organization 級のプラグイン網羅もない。 → Better Auth なら: アプリのコードベース内で完結し、プラグインで機能を盛れる。
  145. 09 — 軸① AI が認証を書く なぜコードベース型 OSS は AI と相性がいいのか

    AI が読める AI が⽣成できる AI が規約に沿える auth.ts‧スキーマ‧呼び出し箇所がリポジトリ内 にある 設定からテーブル定義を機械的に導出(CLI) 公式 Skills / ドキュメントを参照させられる SaaS は管理画⾯の「外」に実体があり、AI に渡せる⼿掛かりが少ない。公式の AI 向け4リソース: リソース 何か いつ使うか Ask AI in docs ドキュメント内で AI に直接質問する UI 仕様をその場で確認 llms.txt docs 全体を LLM 向けに構造化したテキスト ⽂脈をまとめて渡す ドキュメント MCP 検索‧例‧セットアップ補助を MCP で提供 エディタから最新 docs を引く Skills 規約‧安全パターンを教えるエージェントスキル 作法どおり実装させる
  146. 09 — 軸① AI が認証を書く CLI — ⼈間が(AI も)スキーマを⼿書きしない -/

    auth.ts — プラグインを足すだけ -/ テーブル定義は書かない import { organization, twoFactor } from "better-auth/plugins"; export const auth = betterAuth({ generate database: -* adapter -/, emailAndPassword: { enabled: true }, ↓ DB レイヤで出⼒先が変わる plugins : [organization(), twoFactor()], }); npx @better-auth/cli@latest generate npx @better-auth/cli@latest migrate Prisma Drizzle Kysely schema.prisma schema.ts schema.sql organization → 組織/メンバー/招待のテーブル、twoFactor → 2FA カラムが ⾃動で追従。フラグ: --output / --config / --yes。
  147. 09 — 軸① AI が認証を書く ドキュメント MCP — AI に「最新の正解」を引かせる

    Cursor / Claude Code / Open Code → mcp.better-au th.com/mcp → 公式 docs の最新 npx auth@latest mcp --cursor npx auth@latest mcp --claude-code npx auth@latest mcp --open-code # フラグ無し → 対応ターゲット一覧 認証機能としての MCP プラグイン(→ 6-10)とは別物 — こちらは「ドキュ メントを引くための MCP」。AI の古い記憶ではなく公式最新を参照させ る。 npx auth@latest mcp
  148. 09 — 軸① AI が認証を書く 公式 Skills — AI に「作法」を守らせる

    SKILL.md 等のポータブル指⽰ファイルで、規約‧安全パターン‧ 「docs のどこを⾒るか」をエージェントに教える。公式パックは better-auth/skills。 npx skills add better-auth 規約をプロンプトに毎回書く代わりに固定 →「それっぽいが間違って いる」認証コードの事故を減らす。認証はミスがそのまま脆弱性になる 領域。
  149. 09 — 軸① AI が認証を書く llms.txt と Ask AI in

    docs llms.txt Ask AI in docs docs 全体を LLM 向け構造化テキストで公開。 docs サイト上の質問 UI。ページを横断して探さず、その場で 解決。 better-auth.com/llms.txt # 索引 /llms.txt/docs/<path>.md # 各ページ HTML スクレイピング不要 — ページ単位の Markdown を直接コンテ キストへ。 軸①の中では最も軽量な⼊⼝。
  150. 09 — 軸① AI が認証を書く 軸①のまとめ — 4要素が1つの状態へ収束する CLI MCP‧llms.txt

    Skills Ask AI スキーマ⾃動化 最新ドキュメント供給 作法の矯正 その場の疑問 ↓ 「AI が、正しい⽂脈で、規約どおりに、 認証コードを書ける」状態。 前提 = 認証がコードとして⼿元にあること。