はじめに
個人開発のWebサービスで認証機能が必要になったとき、選択肢は多数あります:
- NextAuth.js(Auth.js)
- Firebase Authentication
- Supabase Auth
- Clerk
今回はClerkを選びました。理由は「最も少ないコードで、最も多くの機能が手に入る」からです。
なぜ Clerk か
| 比較項目 | Clerk | NextAuth.js | Firebase Auth |
|---|---|---|---|
| 導入コード量 | 3ファイル | 10ファイル以上 | 5ファイル以上 |
| UI | 組み込み済み | 自作 | 自作 |
| Google OAuth | ダッシュボードでON | Provider設定 + Callback | Console設定 |
| 日本語化 |
jaJP ロケール |
自作 | 自作 |
| ユーザー管理画面 | ダッシュボード | なし | Firebase Console |
| 無料枠 | 10,000 MAU | — | 無制限 |
| 料金 | $0〜$25/月 | 無料 | 無料〜 |
10,000 MAU無料は個人開発には十分すぎます。UIが組み込み済みなので、サインイン/サインアップ画面を自作する必要がありません。
実装手順
1. インストール(30秒)
npm install @clerk/nextjs @clerk/localizations
2. 環境変数(1分)
Clerk ダッシュボードからキーを取得して .env.local に設定:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/dashboard
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/dashboard
3. layout.tsx に Provider 追加(2分)
// app/layout.tsx
import { ClerkProvider } from "@clerk/nextjs";
import { jaJP } from "@clerk/localizations";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ja">
<ClerkProvider localization={jaJP}>
<body>{children}</body>
</ClerkProvider>
</html>
);
}
localization={jaJP} を渡すだけで、サインイン画面・エラーメッセージがすべて日本語になります。
4. Middleware で認証チェック(3分)
// middleware.ts
import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server";
const isPublicRoute = createRouteMatcher([
"/",
"/features",
"/guide",
"/faq",
"/terms",
"/privacy",
"/contact",
"/sign-in(.*)",
"/sign-up(.*)",
"/api/webhooks(.*)",
"/api/health",
]);
export default clerkMiddleware(async (auth, request) => {
if (!isPublicRoute(request)) {
await auth.protect();
}
});
export const config = {
matcher: ["/((?!.*\\..*|_next).*)", "/", "/(api|trpc)(.*)"],
};
これだけで全ページに認証がかかります。 公開ページだけを明示的にリストアップし、それ以外は自動で protect() が適用されます。
5. サインインページ(2分)
// app/sign-in/[[...sign-in]]/page.tsx
import { SignIn } from "@clerk/nextjs";
export default function Page() {
return (
<div className="flex justify-center items-center min-h-screen">
<SignIn />
</div>
);
}
// app/sign-up/[[...sign-up]]/page.tsx
import { SignUp } from "@clerk/nextjs";
export default function Page() {
return (
<div className="flex justify-center items-center min-h-screen">
<SignUp />
</div>
);
}
UIは完全にClerkが提供。 メールアドレス入力、パスワード設定、メール認証、Google OAuthボタンがすべて含まれています。
完了!
以上の5ステップで認証が動きます。実作業時間は10分以下です。
API Route での認証
// app/api/invoices/route.ts
import { auth } from "@clerk/nextjs/server";
export async function GET() {
const { userId } = await auth();
if (!userId) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
// userId を使ってDBからデータ取得
const invoices = await prisma.invoice.findMany({
where: { user: { clerkId: userId } },
});
return NextResponse.json(invoices);
}
auth() を呼ぶだけでユーザーIDが取れます。
Google OAuth の有効化
- Clerk ダッシュボード → Configure → SSO Connections → Google をON
- Google Cloud Console でOAuth同意画面を設定
- Client ID / Client Secret を Clerk に登録
Clerk側は「Google」のトグルをONにするだけ。Google Cloud Console側の設定は必要ですが、Clerkのドキュメントに手順が書かれています。
DB連携パターン: getOrCreateUser
ClerkはユーザーデータをClerk側で管理しますが、アプリ固有のデータ(クレジット残高、請求書など)はDBに保存する必要があります。
初回アクセス時にDB作成する方式が最もシンプルです:
// lib/auth.ts
export async function getOrCreateUser() {
const { userId } = await auth();
if (!userId) throw new Error("Unauthorized");
let user = await prisma.user.findUnique({
where: { clerkId: userId },
});
if (!user) {
// Clerkからメールアドレスを取得
const clerkUser = await clerkClient.users.getUser(userId);
const email = clerkUser.emailAddresses[0]?.emailAddress;
// トランザクションでユーザー作成 + 初期クレジット付与
user = await prisma.$transaction(async (tx) => {
const newUser = await tx.user.create({
data: {
clerkId: userId,
email,
creditBalance: 3, // 無料お試し3回分
},
});
await tx.creditTransaction.create({
data: {
userId: newUser.id,
amount: 3,
type: "initial_grant",
description: "新規登録特典",
},
});
return newUser;
});
}
return user;
}
本番環境への移行
ClerkにはDevelopmentとProductionの2つのインスタンスがあります。本番移行時のチェックリスト:
- Clerk ダッシュボードで Production instance を作成
- カスタムドメイン(例:
clerk.toruca.app)のDNS設定 - 環境変数を Production キーに差し替え
- Google OAuth の Authorized redirect URIs を本番ドメインに更新
- Google OAuth 同意画面を「本番環境」に切り替え
まとめ
- npm install → Provider → Middleware → サインインページ の4ステップで完了
-
jaJPロケールで日本語化が1行 - Google OAuthはダッシュボードでトグルON
-
auth()でどこでもユーザーIDが取れる - 10,000 MAU無料で個人開発には十分
認証はサービスの根幹なので、自前実装よりも実績のあるサービスに任せるのが安全です。
この構成で認証を実装したサービス: トルカ 振込アシスト — 請求書からAIで全銀フォーマットの振込データを自動生成