Clerkは、サインイン画面・ユーザー管理・セッション管理をまとめて外部化できる、React・Next.jsに寄せた認証SaaSです。この記事では、Next.js 16へClerk認証を組み込む手順をコード付きで示し、2026年3月のCore 3で変わった書き方、60秒で失効するセッショントークンの仕組み、日本語化できる範囲と英語のまま残る画面、MRU課金の料金を整理します。最後に、Auth0やAuth.jsとの選び分けを条件付きで言い切ります。
まとめ:Clerk認証をReact案件で採用する条件と見送る場面
Next.jsやReactでB2Cの会員機能を短期間で出す案件なら、Clerkは有力な選択肢です。サインイン画面とプロフィール画面がコンポーネントで提供され、アプリ側の作業は鍵の設定・Providerの配置・サーバー側の認可判定にほぼ絞られます。無料のHobbyでも1アプリあたり50,000MRUまで使えます。
見送るのは、Next.js以外のバックエンドが主役の構成、SAML接続を多数抱えるB2B、ログイン周りの全画面を日本語で揃える必要がある案件です。2026年10月時点の最新SDKは@clerk/nextjs 7.9系で、Core 3以前の記事にあるauthMiddlewareやcreateRouteMatcher前提の書き方は、そのまま写さないでください。
Clerk認証の仕組み:2種類のトークンとSDKが受け持つ処理の範囲
Clerkを入れると、ユーザーのパスワードやソーシャルログインの連携情報はClerk側に保存され、アプリは「誰がログインしているか」を署名付きトークンで受け取るだけになります。
Clerkが肩代わりする範囲:画面部品・ユーザー台帳・セッション発行
Clerkが提供するのは、SignInやUserButtonなどのReactコンポーネント、ユーザーと組織(Organizations)の台帳、セッショントークンの発行と更新です。メール+パスワード、メールコード、Google・GitHubなどのソーシャルログインはダッシュボードの切り替えで有効にできます。
アプリ側に残る仕事は、どの画面・どのAPIを誰に許すかという認可の判定です。SDKは公式リポジトリclerk/javascriptにまとまっており、Next.js用・React用・Express用・サーバー検証用(@clerk/backend)が同じ版系列で公開されています。
__clientと__sessionの2つのCookie、50秒ごとに走る自動更新
公式のHow Clerk worksによると、Clerkは長命のクライアントトークンと短命のセッショントークンを組み合わせています。クライアントトークンはClerkのFrontend APIのドメインに__clientというHttpOnly Cookieで置かれ、セッションの正本になります。
アプリのドメインに置かれる__sessionは有効期限60秒のJWTです。フロントエンドSDKが50秒間隔で更新を呼ぶため、ユーザーを強制ログアウトしても既発行トークンは最長60秒で失効します。サーバー側はこのJWTの署名を検証するだけで済み、リクエストごとにClerkへ問い合わせる必要はありません。
| 項目 | クライアントトークン | セッショントークン |
|---|---|---|
| Cookie名 | __client | __session |
| 置き場所 | Frontend APIのドメイン | アプリのドメイン |
| 有効期限 | ブラウザ依存 | 60秒 |
| HttpOnly | あり | なし |
本番ではclerk.example.comのようにFrontend APIを自社サブドメインへCNAMEで向けるため、DNSの設定作業が発生します。
Next.js 16のClerk導入:clerk initとproxy.ts作成
ここからは公式のNext.js Quickstartに沿って、App Routerのアプリへ組み込む作業を順に示します。
clerk initで鍵とproxy.tsを生成する手順と環境変数の置き場所
Clerk CLIのinitを実行すると、パッケージの追加、.env.localへの鍵の書き込み、proxy.tsの生成までが一度に済みます。Next.js 16以降はproxy.ts、15以前はmiddleware.tsが作られ、中身はどちらもclerkMiddleware()の呼び出しです。
npx -y clerk@latest init --framework next --pm npm
npx -y clerk@latest doctor
# .env.local(initが書き込む)
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxxxxxxx
CLERK_SECRET_KEY=sk_test_xxxxxxxx
CLERK_SECRET_KEYはサーバー専用です。NEXT_PUBLIC_を付けた変数へ移すとブラウザに配布されるため、Vercelなどの環境変数でも公開側に置かないでください。
layout.tsxにClerkProviderとShowを置いてサインイン画面を出す
次にルートレイアウトの<body>内をClerkProviderで包み、ログイン状態で表示を切り替えます。Core 3からはShowコンポーネントのwhen属性で切り替える書き方が標準です。
// app/layout.tsx
import { ClerkProvider, SignInButton, SignUpButton, Show, UserButton } from '@clerk/nextjs'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ja">
<body>
<ClerkProvider>
<header>
<Show when="signed-out"><SignInButton /><SignUpButton /></Show>
<Show when="signed-in"><UserButton /></Show>
</header>
{children}
</ClerkProvider>
</body>
</html>
)
}
この時点でnpm run devを起動すると、Clerkがホストするサインイン画面へ遷移し、登録とログインまで動きます。
Server ComponentとRoute Handlerの未認証アクセス拒否
画面やAPIの保護は、データを読む場所でauth()を呼んで判定します。auth()のリファレンスにあるとおり非同期関数なので、必ずawaitを付けます。
// app/dashboard/page.tsx
import { auth } from '@clerk/nextjs/server'
export default async function Dashboard() {
const { isAuthenticated, redirectToSignIn, userId } = await auth()
if (!isAuthenticated) return redirectToSignIn()
return <p>ログイン中のユーザー: {userId}</p>
}
// app/api/orders/route.ts
export async function GET() {
const { isAuthenticated, userId } = await auth()
if (!isAuthenticated) return new Response('Unauthorized', { status: 401 })
// userIdで絞り込んだ注文だけを返す
}
APIでは「ログインしているか」に加えて「そのuserIdのデータか」まで照合します。他人の注文IDを指定されても返さない条件を、SQLの絞り込みに入れておくのが基本です。
Core 3で変わったClerkの書き方:パッケージ改名と認可位置の見直し
npm registryの公開日を見ると、@clerk/nextjs 7.0.0と@clerk/react 6.0.0は2026年3月3日に出ています。これがCore 3で、それ以前の解説記事のコードは一部が動かないか非推奨です。
Core 3移行時のパッケージ改名と認証表示コンポーネントの対応表
Core 3のアップグレードガイドで示された主な変更を表にまとめます。移行はnpx @clerk/upgradeでコードを自動変換してから、残りを手で直す順番が推奨されています。
| Core 2までの書き方 | Core 3以降 |
|---|---|
| @clerk/clerk-react | @clerk/react(旧名は非推奨) |
| SignedIn・SignedOut | Show when=”signed-in”など |
| Protect | Showによる表示制御 |
| afterSignInUrl | fallbackRedirectUrl |
| redirectUrl | fallbackRedirectUrl |
| Next.js 13・14対応 | Next.js・Node.jsの対応下限を変更 |
Core 3の対応下限はNext.js 15.2.3以上・Node.js 20.9.0以上です。Next.js 14のまま運用しているアプリは、Clerkの更新より先にNext.js本体の更新計画が要ります。
createRouteMatcherでの一括保護をやめ、データ取得側で判定する理由
clerkMiddleware()のリファレンスでは、パス単位で保護するcreateRouteMatcher()が非推奨と明記され、データを読み書きするコードの近くで認可する方式へ移るよう案内されています。
背景には、ミドルウェアだけに認可を任せる設計の弱さがあります。2025年にはNext.jsミドルウェアの認可を迂回できるCVE-2025-29927が公表されました。proxy.tsはセッションの受け渡しに使い、権限の判定はページ・Route Handler・Server Actionの中で行う二段構えにしておくと、同種の欠陥が出ても被害が広がりません。
Next.js以外のバックエンドでClerkのJWTを検証する手順と同期処理
フロントはNext.js、APIはExpressや別言語という構成では、APIサーバー側でセッショントークンを検証する処理を自分で組みます。
authenticateRequestによる公開鍵と許可オリジンの検証例
Manual JWT verificationでは、@clerk/backendのauthenticateRequest()を使う方法が推奨されています。jwtKeyに公開鍵を渡すと、Clerkへ通信せずに署名・有効期限を検証できます。
import { createClerkClient } from '@clerk/backend'
const clerk = createClerkClient({
secretKey: process.env.CLERK_SECRET_KEY,
publishableKey: process.env.CLERK_PUBLISHABLE_KEY,
})
export async function handler(req: Request) {
const { isAuthenticated } = await clerk.authenticateRequest(req, {
authorizedParties: ['https://app.example.com'],
jwtKey: process.env.CLERK_JWT_KEY,
})
if (!isAuthenticated) return new Response('Unauthorized', { status: 401 })
}
authorizedPartiesはトークンのazpクレームと照合する許可オリジンの一覧です。省略するとCSRFの余地が残ると公式に書かれているため、本番では必ず指定します。署名方式はRS256で、検証の考え方はJWTの構造と署名検証の仕組みと同じです。
Webhookでユーザーを自社DBへ同期するときの遅延と取りこぼし対策
注文テーブルなどからユーザーを参照するため、Clerkのユーザーを自社DBへ写すことがあります。Webhook同期のガイドではuser.created・user.updated・user.deletedを受け、CLERK_WEBHOOK_SIGNING_SECRETで署名を検証します。
// app/api/webhooks/route.ts
import { verifyWebhook } from '@clerk/nextjs/webhooks'
import type { NextRequest } from 'next/server'
export async function POST(req: NextRequest) {
try {
const evt = await verifyWebhook(req)
if (evt.type === 'user.created') {
// evt.data.id をキーに自社DBへupsertする
}
return new Response('ok')
} catch {
return new Response('Error verifying webhook', { status: 400 })
}
}
同じガイドに、配信は保証されず遅延もあり得ると書かれています。登録直後の画面で自社DBの行を前提にすると、行がまだ無い瞬間に500エラーになります。初回アクセス時にuserIdで行を作るupsertを併用し、Webhookは補正用と割り切る設計が安全です。
Clerk認証の日本語対応:localizationで訳せる範囲と英語のまま残る画面
「Clerk 日本語」で調べる人が多いのは、初期状態の画面がすべて英語だからです。対応方法と限界を分けて押さえます。
jaJPによる日本語表示の設定とexperimental扱いの運用上の注意
Localizationのドキュメントには日本語(ja-JP)が含まれ、@clerk/localizationsからjaJPを読み込んで渡すだけで切り替わります。
import { jaJP } from '@clerk/localizations'
<ClerkProvider localization={jaJP}>
{children}
</ClerkProvider>
同じページで、この機能はexperimentalで予告なく変わり得ると明記されています。文言の一部だけ差し替えたい場合はjaJPを展開してキーを上書きできますが、SDK更新のたびに表示を目視で確かめる手順をリリース作業に入れておきます。
Account Portalとダッシュボードは英語のまま:日本向け案件の影響
翻訳が効くのはアプリに埋め込んだClerkコンポーネントの文言だけで、ClerkがホストするAccount Portalは英語のままと公式に書かれています。サインイン画面をホスト側に任せる構成だと、日本語の利用者に英語画面が出ます。
回避策は、SignInコンポーネントを自社ドメインのページへ埋め込み、すべての導線をそこへ寄せることです。管理者が触るダッシュボードも英語なので、運用担当が英語UIを扱えるかも導入前に確認しておきます。
Clerk認証の料金:MRU課金の数え方とHobby・Pro・Businessの境目
Clerkの課金単位は、一般的なMAUではなくMRU(Monthly Retained User)です。料金は公式の料金ページの2026年10月時点の値で整理します。
MRUの定義と1アプリ5万人の無料枠、超過単価0.02ドルの段階制
MRUは、サインアップから24時間以上たってから月内に再訪したユーザーだけを数えます。登録した日にしか使わなかった人は課金対象になりません。どのプランも1アプリあたり50,000MRUまで含まれ、超過分はPro・Businessで段階制の単価がかかります。
| プラン | 月額(月払い/年払い) | 含まれるMRU | 超過単価(1MRUあたり月額) |
|---|---|---|---|
| Hobby | 無料 | 50,000 | 超過時はProへ移行 |
| Pro | 25ドル/20ドル | 50,000 | 人数帯別の段階制(単価は表の直後) |
| Business | 300ドル/250ドル | 50,000 | Proと同じ段階制 |
| Enterprise | 個別見積(年払い) | 個別 | 個別 |
超過単価は、5万超〜10万:0.02ドル、10万超〜100万:0.018ドルです。たとえば月間の再訪ユーザーが8万人なら、Proの超過3万人×0.02ドルで600ドルが基本料に加わる計算です。
MFA不可とセッション7日固定:Hobbyで本番運用できない条件
無料のHobbyは人数枠こそProと同じですが、MFAが使えず、セッション期間は7日固定です。Clerkのブランド表示も外せません。管理画面を持つ業務アプリや、社内規程で多要素認証が必須の案件は、最初からPro以上で見積もります。
B2B向けに顧客企業ごとのSAML接続を張る場合、Pro・Businessに含まれるのは1接続までで、2〜15接続目は1接続あたり月75ドルです。SOC2レポートの提出を求められる取引ならBusinessが必要になります。
ClerkとAuth0・Auth.jsの選び分け:採用すべき条件と見送る場面
認証の外部化は後から移すのが難しい判断です。ここでは受託開発の現場で使っている判定の条件を、そのまま言い切ります。
Clerkを採用すべき条件:Next.jsのB2Cアプリで会員機能を短期で出す
採用するのは、フロントがNext.jsかReactで、利用者が一般消費者中心、SSO接続は0〜1本、という3条件がそろう案件です。この場合、画面部品とセッション更新を自作する工数がまるごと消え、月の再訪5万人までは無料で検証できます。
同じ顧客ID基盤でもAuth0はMAU課金で、規模が増えたときの金額の伸び方が異なります。両者の差はAuth0の料金とMAU課金の増え方と並べて比べてください。
Clerkを見送る場面:非React構成・SAML多数接続・全画面日本語化
見送るのは次のどれかに当てはまる案件です。LaravelのBladeやSpring MVCなどサーバー側で画面を描画し、Reactの部品を使わない構成。顧客ごとのSAML接続が10本を超え、接続料だけで月675ドルを超えるB2B。ホスト画面まで日本語が必須の案件です。
ユーザー情報を自社DBに持ち続けたいなら、OSSのAuth.jsのv5導入手順やbetter-authの使い方、DBの行レベル権限と組むならSupabase Authの設計判断が候補です。既存会員DBからの移行や複数サービスの統合ログインを含めて設計したい場合は、認証基盤・ID管理システム開発として要件整理から相談を受けています。
Clerk認証の導入前によくある質問:無料枠・日本語対応・移行と選定
Clerkの導入検討でよく出る質問に、2026年10月時点の公式情報をもとに答えます。
Clerkは無料でどこまで使えますか?
Hobbyプランは無料で、1アプリあたり50,000MRUまで使えます。MRUはサインアップから24時間以上たって再訪したユーザーだけを数えるため、登録だけで離脱した人は含まれません。ただしMFAは使えず、セッション期間は7日固定、Clerkのブランド表示も残ります。本番の業務アプリならPro(月25ドル、年払いなら月20ドル)からの見積もりが現実的です。
Clerkのサインイン画面は日本語にできますか?
アプリに埋め込むコンポーネントは、@clerk/localizationsのjaJPをClerkProviderに渡せば日本語になります。ただし機能はexperimental扱いで、ClerkがホストするAccount Portalは英語のままです。日本語の利用者に英語画面を見せたくない場合は、サインイン画面を自社ページに埋め込む構成にします。
authMiddlewareを使った古い記事のコードは動きますか?
動かない前提で読み替えてください。現行の@clerk/nextjs 7系ではclerkMiddleware()を使い、Next.js 16ではproxy.tsに置きます。パス単位で保護するcreateRouteMatcher()も非推奨になり、ページやRoute Handlerの中でawait auth()を呼んで判定する書き方が推奨です。
ClerkとAuth0はどちらを選べばよいですか?
Next.jsかReactが主体で、一般消費者向けの会員機能を短期で出すならClerkが向いています。サーバー側で画面を描画する従来型のWebアプリ、エンタープライズ向けのSAML接続を多数張る構成、Actionsでログイン処理に独自の手順を差し込みたい場合はAuth0の方が適した選択肢です。課金単位もClerkはMRU、Auth0はMAUと異なります。
Clerkのユーザー情報を自社データベースに保存できますか?
できます。user.createdなどのWebhookを受け、verifyWebhook()で署名を確かめてから自社DBへupsertします。配信は保証されず遅延もあるため、登録直後の処理は自社DBの行を前提にしないでください。必要な属性がセッショントークンのクレームに収まるなら、DBへ写さずトークンから読む方が整合性を保てます。
関連記事
- Auth0の料金はいくら?MAU課金の実額と無料枠を超えた後の増え方を解説【2026年版】:ClerkのMRU課金と比べるための、Auth0側の料金の伸び方。
- Auth0とOktaの違い: 顧客IDと従業員IDで分かれる選定基準と料金・実装の判断【2026年9月時点】:顧客ID向けと従業員ID向けで認証SaaSを分ける判断軸。
- Auth.jsとは?NextAuthとの違い・v5導入手順とCredentials・ロール認可の実装コード:Clerkを見送ってOSSで組む場合のNext.js認証の実装。
- JWTとは?構造・署名検証の仕組みとセッション・OAuth/OIDCとの違いを実装視点で解説:Clerkのセッショントークンを検証するときの前提知識。
- CIAMとは?顧客ID基盤の設計と会員DB移行・同意管理を実装視点で解説:会員DBの移行や同意管理まで含めた顧客ID基盤の設計。