認証/認可はすべてのWebアプリケーションに必須でありながら、実装ミスがセキュリティ事故に直結する「間違えられない」領域です。Claude Codeを使えば、認証ライブラリのセットアップ、RBAC設計、ミドルウェアでの認可チェック、セキュリティベストプラクティスの適用を正確かつ高速に行えます。
この記事では、2026年時点の主要な認証ソリューション——Better Auth・Clerk・Supabase Auth——をClaude Codeで実装する具体的な手順を解説します。Auth.js v5からBetter Authへの移行背景、RBAC設計、ミドルウェア保護、Supabase RLS(Row Level Security)まで、CLAUDE.md設定テンプレート付きで紹介します。
Better Auth vs Clerk vs Supabase Auth ── 選択基準
2025年9月、Auth.js(NextAuth)の開発チームがBetter Authチームに合流しました。Auth.js v5は長期ベータのまま安定版に至らず、新規プロジェクトにはBetter Authが推奨されています。
| 項目 | Better Auth | Clerk | Supabase Auth |
|---|---|---|---|
| 種別 | OSS(自前ホスト) | SaaS | SaaS + OSS |
| 料金 | 無料(MAU無制限) | $0〜$20+/月(50K MAU無料) | $0〜$20+/月(50K MAU無料) |
| DB | 必須(Prisma/Drizzle等) | 不要(Clerk管理) | Supabase内蔵 |
| プリビルトUI | プラグインで提供 | 完全なUIコンポーネント | 自作が必要 |
| RBAC | プラグイン | Organization + Metadata | RLS(Row Level Security) |
| ベンダーロック | なし | 中程度 | 中程度 |
| Claude Code連携 | OSSのためコード生成が自由 | 公式MCP Server提供 | MCP Server提供 |
CLAUDE.mdに認証/認可ルールを記述する
## 認証・認可ルール ### セキュリティ基本方針 - パスワードはbcrypt(saltRounds: 12以上)でハッシュ化 - セッションIDは認証成功後に必ず再生成 - Cookie設定: httpOnly=true, secure=true, sameSite="lax" - JWTの秘密鍵は環境変数で管理(ソースコードにハードコード禁止) ### 認可チェック(CVE-2025-29927対策) - ミドルウェアだけでなく、Server Component / API Route内でも二重チェック (Next.jsミドルウェアバイパス脆弱性の教訓) - RBACロール: admin, editor, viewer の3段階 - 機密操作(削除・設定変更)はadminロール必須 ### 禁止事項 - ハードコードされたシークレット - エラーメッセージに内部情報を含めない("パスワードが違います"ではなく"認証に失敗しました") - ユーザー入力は必ずサニタイズ - SQLインジェクション: パラメータ化クエリ必須
x-middleware-subrequestヘッダーを使ったミドルウェアバイパス脆弱性が報告されました。認可チェックはミドルウェアだけに頼らず、Server Component / API Route内でも必ず二重チェックしてください。Better Auth ── Auth.jsの後継で認証を実装する
Better AuthはTypeScriptネイティブの認証フレームワークで、Auth.jsチームが合流したことで事実上の後継になりました。DB必須ですが、Prisma/Drizzle/Kyselyなどの主要ORMにすべて対応しています。
Better Auth + Prisma + Next.js 16 のセットアップをしてください。 要件: - メール/パスワード認証 - Google/GitHub OAuth - JWTセッション - RBACロール(admin, editor, viewer) - PrismaスキーマにUser/Session/Account/Verificationモデル追加 - ミドルウェアでの認可チェック(二重チェック)
import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { nextCookies } from "better-auth/next-js";
import { prisma } from "@/lib/prisma";
export const auth = betterAuth({
database: prismaAdapter(prisma, { provider: "postgresql" }),
emailAndPassword: { enabled: true },
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
},
github: {
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
},
},
plugins: [nextCookies()],
});
import { createAuthClient } from "better-auth/react";
export const { signIn, signUp, signOut, useSession } = createAuthClient({});
import { auth } from "@/lib/auth";
import { toNextJsHandler } from "better-auth/next-js";
export const { GET, POST } = toNextJsHandler(auth);
import { auth } from "@/lib/auth";
import { headers } from "next/headers";
export default async function DashboardPage() {
const session = await auth.api.getSession({
headers: await headers(),
});
if (!session) {
redirect("/login");
}
return <div>ようこそ、{session.user.name}さん</div>;
}
Clerk ── 最速でプリビルトUIの認証を組み込む
Clerkはプリビルトの認証UI(サインイン/サインアップフォーム、ユーザーメニュー等)を提供するSaaSで、最小限のコードで認証を実装できます。Claude Code向けの公式MCPサーバーも提供しています。
# Claude CodeにClerk MCPを追加 claude mcp add clerk --transport http https://mcp.clerk.com/mcp # → Claude CodeがClerkのSDKスニペットを正確に取得できるようになる
Clerk + Next.js 16 でサインイン/サインアップを実装してください。 要件: - ClerkProvider でアプリ全体をラップ - /sign-in, /sign-up にClerkのプリビルトUIを配置 - middleware.ts でClerk認証ミドルウェアを設定 - 公開ルート: /, /about, /pricing - 保護ルート: /dashboard以下すべて - RBACはpublicMetadataでロール管理(admin/member)
import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server";
const isPublicRoute = createRouteMatcher(["/", "/about", "/pricing", "/sign-in(.*)", "/sign-up(.*)"]);
export default clerkMiddleware(async (auth, req) => {
if (!isPublicRoute(req)) {
await auth.protect();
}
});
export const config = {
matcher: ["/((?!_next|[^?]*\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)"],
};
// ミドルウェアでのロールチェック
export default clerkMiddleware(async (auth, req) => {
if (req.nextUrl.pathname.startsWith("/admin")) {
const session = await auth();
const role = session.sessionClaims?.metadata?.role;
if (role !== "admin") {
return NextResponse.redirect(new URL("/", req.url));
}
}
});
// Server Componentでのロールチェック(二重チェック)
import { currentUser } from "@clerk/nextjs/server";
export default async function AdminPage() {
const user = await currentUser();
if (user?.publicMetadata?.role !== "admin") {
redirect("/");
}
return <div>管理画面</div>;
}
Supabase Auth ── RLSで行レベルの認可を実現する
Supabase AuthはPostgreSQLのRLS(Row Level Security)と統合されており、データベースレベルで「誰がどのデータにアクセスできるか」を制御できます。
Supabase Auth + Next.js 16 SSR でセットアップしてください。 要件: - @supabase/ssr を使用(@supabase/auth-helpersは非推奨) - createBrowserClient(クライアント)とcreateServerClient(サーバー)の2種 - proxy.ts でAuth tokenリフレッシュ(Server Componentsはcookie書き込み不可のため) - profilesテーブルにRLSポリシー(自分のデータのみ読み書き可)
-- テーブルにRLS有効化 ALTER TABLE profiles ENABLE ROW LEVEL SECURITY; -- SELECT: 自分のデータのみ CREATE POLICY "ユーザーは自分のプロフィールのみ閲覧可能" ON profiles FOR SELECT USING ( (SELECT auth.uid()) = user_id ); -- INSERT: 自分のデータのみ作成 CREATE POLICY "ユーザーは自分のプロフィールのみ作成可能" ON profiles FOR INSERT TO authenticated WITH CHECK ( (SELECT auth.uid()) = user_id ); -- UPDATE: 自分のデータのみ更新 CREATE POLICY "ユーザーは自分のプロフィールのみ更新可能" ON profiles FOR UPDATE TO authenticated USING ( (SELECT auth.uid()) = user_id ) WITH CHECK ( (SELECT auth.uid()) = user_id ); -- マルチテナント: JWTのteam_id情報で制御 CREATE POLICY "チームメンバーのみアクセス可能" ON team_data FOR ALL TO authenticated USING ( team_id IN ( SELECT (auth.jwt() -> ''app_metadata'' ->> ''teams'')::uuid[] ));
RBAC(Role-Based Access Control)をClaude Codeに設計させる
以下のWebアプリケーションのRBACロール設計を行ってください。 アプリ概要: チームコラボレーションツール ユーザー種別: - admin: 全操作可能(メンバー管理、請求管理) - editor: コンテンツの作成・編集・削除 - viewer: 閲覧のみ 設計してほしいもの: 1. ロールと権限のマトリックス表 2. DBスキーマ(Prisma)のUser.roleカラム設計 3. 認可チェックのユーティリティ関数 4. Next.js proxy.ts でのルートベース認可 5. Server Component内での二重チェックパターン
// lib/permissions.ts
type Role = "admin" | "editor" | "viewer";
type Permission = "read" | "create" | "update" | "delete" | "manage_users" | "manage_billing";
const rolePermissions: Record<Role, Permission[]> = {
admin: ["read", "create", "update", "delete", "manage_users", "manage_billing"],
editor: ["read", "create", "update", "delete"],
viewer: ["read"],
};
export function hasPermission(role: Role, permission: Permission): boolean {
return rolePermissions[role]?.includes(permission) ?? false;
}
export function requirePermission(role: Role | undefined, permission: Permission): void {
if (!role || !hasPermission(role, permission)) {
throw new Error("権限がありません");
}
}
// app/admin/users/page.tsx
import { auth } from "@/lib/auth";
import { headers } from "next/headers";
import { requirePermission } from "@/lib/permissions";
import { redirect } from "next/navigation";
export default async function AdminUsersPage() {
const session = await auth.api.getSession({ headers: await headers() });
if (!session) redirect("/login");
// ミドルウェアに加えてServer Component内でも権限チェック(二重チェック)
try {
requirePermission(session.user.role, "manage_users");
} catch {
redirect("/");
}
// ... admin only content
}
よくある質問
USING句の条件漏れ等)があると機能しません。Claude Codeに「このRLSポリシーにセキュリティ上の問題がないかレビューして」と依頼するのが有効です。x-middleware-subrequestヘッダーを悪用してミドルウェアの認可チェックをバイパスできる脆弱性です。この教訓から、認可チェックはミドルウェアだけでなくServer Component / API Route内でも二重に行うことが業界標準になりました。CLAUDE.mdに「二重チェック必須」と明記しておきましょう。まとめ
- Better Auth: Auth.jsの後継。OSS・DB自前・MAU無制限。データ所有権を重視するプロジェクトに
- Clerk: プリビルトUI + 公式MCP Server。最速実装。50K MAUまで無料
- Supabase Auth: RLSでDBレベルの認可。PostgreSQL統合プロジェクトに
- RBAC設計: ロール×権限マトリックスをClaude Codeに設計させ、ユーティリティ関数として実装
- 二重チェック: ミドルウェア+Server Component / API Route の2箇所で認可チェック(CVE-2025-29927対策)
- CLAUDE.md: セキュリティ基本方針・認可チェックルール・禁止事項を明記して生成品質を担保
Next.jsとの統合はClaude Code × Next.js完全ガイド、データベース設計はClaude Code × データベース開発ガイド、セキュリティ全般はClaude Codeセキュリティ完全ガイドもあわせてご覧ください。

