ハンズオン

認証と管理者ロール

読み取り専用/読み取り+操作の管理者ロールをDBで管理し、管理APIを保護し、このテンプレートの認証パイプラインを説明します。

認証と管理者ロール

このテンプレートは Better Auth + Drizzle を使用します。RBAC はデータベースに保存し、環境変数での昇格は行いません。

基本: 認証と認可の違い

  • 認証 (Authentication): 誰かを確認する(サインアップ/サインイン)。結果としてセッションが得られます。
  • 認可 (Authorization): その後に何ができるかを決める。このテンプレートでは users テーブルの role が制御します。

ロール:

  • user — すべてのユーザーの既定。
  • admin_ro — 読み取り専用(管理データの閲覧のみ)。
  • admin_rw — 読み取り + 書き込み(クレジット付与などの管理操作を含む)。

空港のアナロジー

保安検査で身分証を提示するのが「認証」(本人確認)。搭乗口で搭乗券を提示するのが「認可」(その便に乗れるかの確認)。

クイック比較

項目認証認可
目的身元の確認(誰か)権限の確認(何ができるか)
タイミング認可より前認証が成功した後
典型入力資格情報(パスワード、メールリンク、ソーシャル)ポリシー/ロール(useradmin_roadmin_rw
出力セッション/アイデンティティ許可された操作と保護されたルート
一般的な標準OIDC、ID トークンOAuth 2.0、スコープ

本テンプレートでは、フロントのトークンではなくサーバーの HttpOnly セッションクッキーを使用し、DB 上の role で認可を行います。

Better Auth とは?

Next.js 向けの軽量で TypeScript ファーストな認証ライブラリです。

  • ストレージ: Drizzle ORM + Postgres(src/lib/auth.ts を参照)。
  • データモデル: userssessionsaccountsverificationssrc/db/schema.ts)。
  • セッション: HttpOnly クッキー + sessions テーブルに保存。サーバールートは auth.api.getSession({ headers }) で読み取ります。
  • 追加フィールド: additionalFieldsuuidrole をセッションに含め、サーバー側のチェックを簡単にします。

シークレットと URL(入門)

  • BETTER_AUTH_SECRET: 認証用のクッキー/トークンに署名・検証するサーバー専用の長い乱数文字列。1 回生成して安全に保管します。
    • 生成: openssl rand -base64 32
    • ローテーション: 値を変更すると全ユーザーがサインアウトされます(既存セッションが無効に)。
  • BETTER_AUTH_URL: 認証ライブラリが使用するサーバーのベース URL(通常はサイト URL)。
  • NEXT_PUBLIC_AUTH_BASE_URL: クライアント側のベース(多くの場合サイト URL と同じ)。
  • クッキーは本番で HttpOnly かつ securesrc/lib/auth.tsadvanced.defaultCookieAttributes を参照)。

サインインが 1 回しか動かない/再起動でセッションが消える場合は、上記の環境変数を確認して dev サーバーを再起動してください。

ロール

  • user: 既定ロール。
  • admin_ro: 読み取り専用。ユーザー/注文の一覧、ユーザーのクレジット閲覧。
  • admin_rw: 読み取り+操作。system_add でクレジット付与も可能。

マイグレーション 0001_add_user_role.sqlusers.role(既定値 user)を追加します。

認可

  • src/lib/authz.ts がセッション/DB からロールを取得します:
    • requireAdminRead()admin_ro/admin_rw を許可。
    • requireAdminWrite()admin_rw を許可。

管理API

  • GET /api/admin/users → ユーザー一覧(page, limit)。
  • GET /api/admin/orders → 支払い済み注文(ページング)。
  • GET /api/admin/users/:uuid/credits → クレジット要約。
  • POST /api/admin/credits/grantsystem_add でクレジット付与。

セットアップ手順

  1. DB をマイグレーション:
pnpm drizzle-kit migrate --config src/db/config.ts
  1. 管理アカウントでエンドポイントを確認。

ロールの変更方法

権威は DB 側に持たせます:

  • SQL:
    update users set role = 'admin_rw' where uuid = '<uuid>';
  • ヘルパー:
    • updateUserRole(uuid, 'admin_ro' | 'admin_rw' | 'user')src/models/user.ts)。

注意

  • 管理アカウントは MFA/SSO と短いセッション期限を推奨。
  • 管理ページはサーバー側でチェックし、未認可はリダイレクト。
  • ロールは .env では管理しません。DB で設定/解除します。

ソーシャルログイン(Google)

  • Google プロバイダは src/lib/auth.tssocialProviders.google で設定され、.envGOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET を参照します。
  • .envGOOGLE_CLIENT_IDGOOGLE_CLIENT_SECRET を設定し、BETTER_AUTH_URLNEXT_PUBLIC_AUTH_BASE_URL が正しいことを確認してください(開発では http://localhost:3000)。
  • Google Cloud Console → Credentials で認可済みリダイレクト URI に次を追加:
    • http://localhost:3000/api/auth/callback/google(開発)
    • https://あなたのドメイン.com/api/auth/callback/google(本番)
  • /[locale]/login のログイン画面に「Google で続行」ボタンが表示され、OAuth フローが開始されます。