結論(おすすめ1つ)
乗り換え先は Clerk を推奨する。
Auth0 からの脱出を検討しているスタートアップ〜中規模チームであれば、Clerk が最も開発体験のコストパフォーマンスに優れている。React/Next.js との統合がファーストクラスで、ユーザー管理 UI がゼロコードで動く。Auth0 特有の「Rules/Actions の暗黙的な実行順」に振り回される時間がなくなるだけでも切り替える価値がある。
比較表(料金/無料枠/移行コスト/対応言語)
| 項目 | Clerk | Supabase Auth | WorkOS |
|---|---|---|---|
| 無料枠 | 月間 10,000 MAU まで | Supabase Free プランに含む(詳細は公式の料金ページで要確認) | AuthKit は月間 1,000,000 MAU まで無料(公式の料金ページで要確認) |
| 有料プランの起点 | 公式の料金ページで要確認 | Pro プランから(公式の料金ページで要確認) | SSO/SCIM 等のアドオンから(公式の料金ページで要確認) |
| Auth0 からの移行コスト | 中(パスワードハッシュ移行が必要) | 中〜低(OSS のため SQL 直投入も可) | 高(エンタープライズ向け再設計が入りやすい) |
| 主な対応 SDK | JS/TS, React, Next.js, Remix, Expo | JS/TS, Python, Dart, Kotlin, Swift | JS/TS, Python, Ruby, PHP, Go, Java |
| 自己ホスト | 不可(SaaS のみ) | 可(OSS) | 不可(SaaS のみ) |
| 特徴 | UI コンポーネント同梱・DX 最優先 | DB と認証が同一プラットフォーム | SSO/SAML/SCIM 等 B2B エンタープライズ特化 |
移行手順
Auth0 → Clerk の移行を、Next.js App Router プロジェクトを例に示す。
1. SDK のインストールと環境変数の設定
npm install @clerk/nextjs
# .env.local
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxxx
CLERK_SECRET_KEY=sk_test_xxxx
2. ミドルウェアの差し替え
Auth0 の withApiAuthRequired / handleAuth を削除し、Clerk のミドルウェアに置き換える。
// middleware.ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'
const isPublicRoute = createRouteMatcher(['/sign-in(.*)', '/sign-up(.*)'])
export default clerkMiddleware((auth, req) => {
if (!isPublicRoute(req)) auth().protect()
})
export const config = {
matcher: [
'/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico)).*)',
'/(api|trpc)(.*)',
],
}
3. Auth0 ユーザーのハッシュ移行
Auth0 Management API でユーザーをエクスポートし、Clerk Backend API へインポートする。bcrypt ハッシュはそのまま渡せる。
# Auth0 ユーザーエクスポート
curl -X GET "https://<YOUR_DOMAIN>/api/v2/users?per_page=100" \
-H "Authorization: Bearer <MGMT_TOKEN>" \
-o auth0_users.json
// scripts/migrate_users.ts
import { createClerkClient } from '@clerk/nextjs/server'
import users from './auth0_users.json'
const clerk = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY })
for (const user of users) {
await clerk.users.createUser({
emailAddress: [user.email],
passwordDigest: user.password_hash,
passwordHasher: 'bcrypt',
externalId: user.user_id, // Auth0 の sub を保持
})
console.log(`migrated: ${user.email}`)
}
4. フック・セッション参照の書き換え
// Before (Auth0)
import { useUser } from '@auth0/nextjs-auth0/client'
const { user } = useUser()
const userId = user?.sub
// After (Clerk)
import { useUser } from '@clerk/nextjs'
const { user } = useUser()
const userId = user?.id
const email = user?.primaryEmailAddress?.emailAddress
サーバーコンポーネントでのセッション取得も同様に差し替える。
// Server Component (Clerk)
import { auth } from '@clerk/nextjs/server'
export default async function Page() {
const { userId } = await auth()
if (!userId) redirect('/sign-in')
// ...
}
向き不向き
Clerk が向くチーム・規模
- Next.js / React / Expo を採用しており、認証 UI を自前で組みたくない
- MAU がまだ少なく、無料枠で本番まで走り切りたいスタートアップ
- Auth0 の Rules/Actions の連鎖デバッグに疲れたチーム
Supabase Auth が向くチーム・規模
- すでに Supabase を DB として利用しており、スタックを統一したい
- PostgreSQL の Row Level Security と認証を密結合した設計を取りたい
- ベンダーロックインを避けたい、将来的に自己ホストの選択肢を残したい
WorkOS が向くチーム・規模
- B2B SaaS でエンタープライズ顧客向けに SSO / SAML / SCIM が必須
- Auth0 の Enterprise プランのコストを下げたい大規模チーム
避けるべきケース
- Clerk: React 系フレームワークを使わないバックエンド専用チーム(SDK の恩恵が薄く、素の API 呼び出しになる)
- Supabase Auth: PostgreSQL 以外の DB が中心で認証だけを切り出したい場合(統合前提の設計のため分離コストが高い)
- WorkOS: 個人〜小規模 B2C サービス(エンタープライズ向け機能を持て余し、設定コストが見合わない)
Top comments (0)