0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js + Clerk を使いこなすために知っておくべきこと

0
Last updated at Posted at 2025-12-19

対象読者:Next.js(App Router)で B2C/B2B SaaS を作っていて、Clerk を「ただ導入する」から「安全に運用できる設計で使う」へ進みたい人
この記事では Cookie/Session の仕組みOrganization(マルチテナント) を軸に、実務でハマらないための体系をまとめます。


1. Clerk って何をしてくれるサービス?

Clerk は一言でいうと Authentication(認証)+ User Management(ユーザー管理)+ Session Management(セッション管理) を提供するサービスです。Next.js 側では Clerk の SDK を通じて「このリクエストは誰のものか」を取り出し、あなたのアプリ(DB/機能)はそれを前提に動きます。(clerk.com)


2. まず押さえるべき “内部イメージ”

Clerk を使う上で一番大事なのは、「ログインしたら終わり」ではなく Session を中心に全てが回る ことです。

  1. ユーザーが Sign in
  2. Clerk が Session を発行(ブラウザに Cookie 等として保持)
  3. 以後のアクセスではブラウザが Cookie を自動送信
  4. Next.js 側は auth() や middleware で Session を検証し、userId 等を得る(clerk.com)

3. 認証と認可を分けて考える(重要)

  • Authentication(認証):あなたは誰?ログインしてる? → userId が取れるか
  • Authorization(認可):その人は “この操作” をしていい? → Role/Permission、org の所属、DB 条件など

Clerk は主に「認証情報(+ org context)を提供」しますが、データ分離や権限チェックの最終責任はアプリ側にあります(ここが事故ポイント)。(clerk.com)


4. Next.js App Router での基本部品(何をどこで使うか)

4.1 clerkMiddleware():入口で “認証状態” を付与する

App Router では middleware を使って、対象ルートで Clerk が認証情報を扱えるようにします。
重要:デフォルトでは何も保護されません(opt-in)。守りたいルートは自分で指定します。(clerk.com)

例(イメージ):

// middleware.ts
import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server";

const isProtectedRoute = createRouteMatcher([
  "/dashboard(.*)",
  "/api(.*)",
]);

export default clerkMiddleware((auth, req) => {
  if (isProtectedRoute(req)) auth().protect();
});

export const config = {
  matcher: [
    // Next.js 推奨の matcher パターン(静的ファイル除外 + API)
    "/((?!_next|.*\\..*).*)",
    "/(api|trpc)(.*)",
  ],
};

createRouteMatcher() を使った保護は Clerk 公式の middleware リファレンスでも触れられています。(clerk.com)

4.2 auth():Server / Route Handler 側で “誰か” を取り出す

App Router では auth()Auth object(認証結果)を取り出します。(clerk.com)

例(Route Handler):

import { auth } from "@clerk/nextjs/server";

export async function GET() {
  const { userId, orgId } = auth();

  if (!userId) return new Response("Unauthorized", { status: 401 });
  // orgId が必要なページならここで弾く
  // if (!orgId) return new Response("No active org", { status: 400 });

  return Response.json({ userId, orgId });
}

5. Session token / JWT を “いつ気にすべきか”

Clerk の session は JWT(session token)として扱われることがあり、必要に応じて claim を拡張できます。(clerk.com)

  • 普通の Web アプリ(Next.js 内で完結)なら:まずは Cookie + auth() を理解すればOK

  • 次の用途が出たら JWT を意識すると良い

    • 外部サービスに渡すトークンが必要(analytics、別バックエンド、CLI など)
    • 「この claim を token に入れて downstream で検証したい」
    • 長期トークンをテンプレで発行したい(JWT templates)(clerk.com)

6. Organization(マルチテナント)の考え方:Active Organization が核心

6.1 “所属してる” と “今その org として操作してる” は別

Organization を使うと、ユーザーは複数 org に所属でき、アプリ内では通常「今どの org を active にしてるか」が重要になります。Clerk の org ガイドでも org を作成/切替し、org 単位で保護する流れが説明されています。(clerk.com)

アプリでよく見る状態:

  • userId はある(ログイン済み)
  • でも orgId がない(active org 未選択)
    → 「Organization を選んでください」画面へ誘導する必要がある

6.2 Organization slug を URL に入れる設計

B2B SaaS で多いのが /{orgSlug}/... 形式です。Clerk 公式には org slug を URL に使うガイドがあり、OrganizationSwitcher や middleware 設定、org-specific rendering の考え方が整理されています。(clerk.com)

この設計での実務ポイント:

  • URL の orgSlug と active org を一致させる(不一致はリダイレクト or 403)
  • link 共有が多い・org 切替が多いなら slug 方式が効く(公式も注意点を提示)(clerk.com)

7. DB 設計の鉄則:必ず “tenant key” を持たせる

Organization を使うなら、DB のすべての “テナント依存データ” に以下のどちらかを入れます:

  • orgId(Clerk の organization id)をそのまま保存
  • もしくは自前 tenant_id を作って clerk_org_id と紐付け

そして 全クエリに WHERE org_id = auth().orgId を入れる
Clerk は orgId を教えてくれますが、データ分離はあなたのアプリの責務です(ここがマルチテナント事故の最大要因)。(clerk.com)

例(擬似コード):

const { userId, orgId } = auth();
if (!userId) throw new Error("Unauthorized");
if (!orgId) throw new Error("No active org");

// ✅ orgId で必ず絞る
const interviews = await db.interview.findMany({
  where: { orgId },
});

8. Role / Permission(認可)の実装パターン

Organization を使うと「org 内の Role/Permission」で管理画面や操作権限を分けるのが王道です(Clerk の org チュートリアルでも “protect routes by Organization and Roles” を扱います)。(clerk.com)

実務ルール:

  • UI だけ隠すのはNG(API/Server Action でも必ず検証)
  • “管理者だけ” は server 側で弾く
  • 迷ったら「最小権限」をデフォルトにする

9. ハマりどころ(よくある症状 → 原因)

9.1 auth() を呼ぶと「middleware が検出できない」系エラー

auth() は middleware が正しく設定されている前提で動きます。matcher がそのルートを対象にしていない等で起きます。(GitHub)

9.2 orgIdundefined/null になる

多くの場合「所属はしているが active org が未設定」か、slug/切替導線や middleware 設定の問題です。実際に同様の相談がコミュニティでも繰り返し出ています(=設計で回避しやすい)。(GitHub)


10. まとめ:Clerk を “使いやすくする知識” の最短ルート

  • Clerk は Session を中心に動く(Cookie 自動送信 + server 側検証)(clerk.com)
  • Next.js(App Router)では clerkMiddleware()auth() が基本セット(clerk.com)
  • Organization では Active Organization / orgId が核心(URL slug 設計も含めて考える)(clerk.com)
  • マルチテナントの安全性は DB の orgId 絞り込みで担保する(ここが最重要)(clerk.com)
  • JWT/claim は「外部連携・別バックエンド・CLI」などが出たら理解を深める(clerk.com)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?