メインコンテンツへスキップ
友田 陽大
認証・認可
認証基盤
Cognito
OIDC
セキュリティ
Next.js
技術選定
SSO

2026年の認証基盤の選び方:Cognito・Auth0・Clerk・Supabase Auth 徹底比較と実装・移行ガイド

認証基盤の選定で迷う意思決定者向けに、Cognito・Auth0・Clerk・Supabase Authを評価軸で徹底比較。B2B SSO(SAML/OIDC)、MAU課金、データ主権、Next.js実装、JWT検証、ユーザー移行(lazy migration)まで、実プロジェクトの設計判断を交えて解説します。

公開日
読了時間
19分
著者
友田 陽大
シェア

認証基盤の選定は、一度決めると数年は付き合うことになる「やり直しの効きにくい技術選定」の代表格です。料金体系(MAU課金)、B2BのSSO要件、データ主権、実装速度、そしてベンダーロックインのリスク——これらは後から効いてくるのに、PoC段階では見えにくい。

本記事は、Cognito・Auth0・Clerk・Supabase Authの4つを、意思決定者が「自分たちはどれを選ぶべきか」を判断できる評価軸で整理します。私自身、経済産業大臣賞を受賞したB2B SaaSでAWS Cognitoによるエンタープライズ向けSSO(RS256 JWT・OIDC/SAML)を設計し、サーバーレス決済基盤でCognitoのカスタム認証(Lambdaトリガー)を実装し、サブスクリプション基盤ではtokenVersionによる一括失効を備えたステートレスJWTセッション層を自作しました。その実装経験をもとに、ハイプではなく「どの場面でどれを使うか」に絞って書きます。

注:料金は変動が激しく、ここでは具体的な金額を断定しません。各社の**課金モデル(何で課金されるか)**を理解することが、後悔しない選定の鍵です。最新の金額は必ず各社の公式料金ページで確認してください。


1. TL;DR — どれを選ぶか(一行ずつ)

  • AWS Cognito — すでにAWS中心で、エンタープライズSSO(SAML/OIDC連携)と細かいカスタム認証が要るなら第一候補。DXは荒削りだが、データ主権とコスト効率、AWSサービスとの統合は強力。
  • Auth0 — B2BマルチテナントSaaSで「顧客企業ごとに別のIdPと federation したい」「Organizations単位で管理したい」要件が中心ならベスト。機能は最も成熟、その分プレミアム価格。
  • Clerk — Next.jsでB2C/スタートアップを最速で立ち上げたいなら圧倒的。プリビルトUIとミドルウェアの開発体験(DX)が群を抜く。MAUが増えるとコストは上がりやすい。
  • Supabase Auth — すでにSupabase(Postgres)を使う、もしくはDBのRow Level Security(RLS)と認証を密結合させたいなら自然な選択。OSSでセルフホスト可能、コスト効率も良い。

迷ったら次の問いから入ってください——「これはB2Bか、B2Cか」「データはどこに置く必要があるか」「すでにどのクラウド/DBに乗っているか」。この3つでほぼ絞れます。


2. 評価軸 — 何を見て決めるか

認証基盤を「機能の多さ」で比べると失敗します。見るべきは次の7軸です。

  1. コスト(MAU課金) — 4社とも基本はMAU(Monthly Active User/月間アクティブユーザー)課金です。問題は「何をMAUと数えるか」「SSO/MFAなどの上位機能が別課金か」。Supabaseは通常MAUに加えてSSO MAUやサードパーティMAUを区別して課金します。Cognitoは月次のアクティブユーザー数で段階課金し、脅威対策(Advanced Security / Threat Protection)は別ティアです。ユーザー数が線形に増えるB2Cと、ユーザー数は少ないが単価の高いB2Bでは、最適解が逆転します。
  2. B2B SSO / SAML / OIDC — 顧客企業が「自社のOktaやEntra ID(旧Azure AD)でログインさせたい」と言ってくる世界か。ここはAuth0とCognitoが厚く、Clerk・Supabaseは上位プラン/アドオンで対応します。
  3. セルフホスト / データ主権 — ユーザー資格情報を自社/自国のインフラ内に置く必要があるか(金融・医療・公共)。SupabaseはOSSでフルセルフホスト可能、Cognitoは自社AWSアカウント内のマネージドサービス。Auth0/Clerkは基本SaaS(Auth0はPrivate Cloud等の上位形態あり)。
  4. DX(実装速度) — ローンチまでの速さ。Clerkが頭一つ抜け、Supabaseが続き、Auth0は機能が多い分習熟コスト、Cognitoは最も「組み立てる」必要がある。
  5. カスタム認証 — 標準フローに乗らない要件(独自の多段認証、カードPIN、レガシーDB照合など)。CognitoのLambdaトリガー、Auth0のActionsが代表。
  6. ベンダーロックイン — 移行のしやすさ。標準(OIDC)準拠か、独自APIに深く依存するか。
  7. コンプライアンス — SOC 2 / ISO 27001 / HIPAA / PCI DSS等。CognitoはSOC 1–3・PCI DSS・ISO 27001に準拠し、HIPAA-BAA対象(クラウドのセキュリティ責任分界点)です。

3. 4社+αの比較表

観点AWS CognitoAuth0ClerkSupabase Auth
主戦場AWSネイティブ/エンタープライズCIAMB2Bエンタープライズ/成熟SaaSNext.js B2C/スタートアップPostgresアプリ/RLS密結合
課金モデルMAU段階課金+脅威対策は別ティアMAUティア(B2C/B2B別プラン、上位は商談)無料MAU枠+従量、B2B/SAMLはアドオンMAU+SSO MAU等を区別、無料枠あり
SAML/OIDC連携標準対応(IdPにもSPにもなれる)最も厚い(Enterprise Connections)上位プランのアドオンPro以上でSAML、SSO MAU課金
セルフホスト自社AWS内マネージド基本SaaS(上位形態あり)SaaSのみOSS・フルセルフホスト可
カスタム認証Lambdaトリガーで自在Actionsで拡張限定的(用途特化)DB/Edge Functionsで拡張
Next.js DX普通(要組み立て)最高(専用ミドルウェア)良(SSRヘルパ充実)
DB/RLS統合なし(別途設計)なしなしあり(Postgres RLSと一体)
トークンRS256 JWT(ID/access/refresh)JWTJWTJWT(access/refresh)
ロックイン度中(OIDC準拠だがAWS依存)中〜高(機能依存しやすい)中〜高(UI/SDK依存)低〜中(OSS・Postgres標準)

セルフホスト系・自作という選択肢(と、なぜ避けるべきか)

  • Keycloak / Ory — OSSのIdP/認可基盤。データ主権が絶対要件で、運用チームがある組織には有力。ただし可用性・パッチ・スケールの運用責任を自分で負うことになり、TCO(総保有コスト)はマネージドより高くつくことが多い。
  • 完全自作(roll-your-own auth) — 原則として勧めません。パスワードハッシュ、トークン署名・検証、リフレッシュローテーション、セッション失効、アカウント列挙対策、レート制限、MFA、監査ログ……ここで一箇所でも間違えると、それは即セキュリティインシデントです。認証は「車輪の再発明」がそのまま脆弱性になる領域です。後述するように、私もJWTセッション層は自作しましたが、それは「ユーザーディレクトリ」ではなく「セッション/失効の制御層」に限定し、署名検証など枯れた部分はライブラリに任せています。自作するなら責務を最小に切るのが鉄則です。

4. プロバイダ別ディープダイブ

4.1 AWS Cognito — エンタープライズ&AWSネイティブ

強み。 User Poolは単体で完結したユーザーディレクトリかつOIDCプロバイダで、ローカルユーザーにもフェデレーションユーザーにも統一されたJWT(RS256署名のID/access/refreshトークン)を発行します。OktaやADFS、Entra IDといったワークフォースIdPとSAML 2.0/OIDCで連携でき、CognitoがSP(サービスプロバイダ)として外部の主張を受け取り、自前のトークン形式に正規化してくれる——つまりアプリは「Cognitoのトークン1種類」だけ理解すればよい。これがエンタープライズSSOで効きます。MFAはTOTPとSMSに対応。Identity PoolはAWS STSと連携し、認証済みユーザーにS3やDynamoDBへの一時クレデンシャルを発行できる——AWSリソースへの認可までを一気通貫で扱える点はCognito独自の強みです。

弱み。 ホスト型UI(Managed Login)はカスタマイズの自由度に癖があり、凝ったデザインには向きません。コンソールの体験やドキュメントの導線も、Clerkのような「数分で動く」洗練さはない。属性スキーマの変更がしづらい等、運用の地雷もあります。

理想の場面。 すでにAWS中心の組織、エンタープライズSSO要件、AWSリソースへの認可連携、そしてカスタム認証が要るとき。

カスタム認証(Lambdaトリガー)。 Cognitoの真価はここにあります。DefineAuthChallenge / CreateAuthChallenge / VerifyAuthChallengeResponseの3トリガーで、標準にない多段フローを組めます。私が決済基盤で実装したのは、まさにこのトリガー連携によるカードPIN認証でした。レガシーDBのユーザーをCognitoへLazy移行するUserMigrationトリガーも実用的です(後述)。

4.2 Auth0 — B2Bエンタープライズの王道

強み。 Organizations機能が秀逸で、B2Bマルチテナント——「顧客企業ごとに、それぞれのブランドとフェデレーションログインを提供する」——を正面からサポートします。顧客企業が自社のIdPを持ち込むEnterprise Connections(SAML、OIDC、Entra ID等)は最も厚く、B2B APIへのマシン間(M2M)アクセスや、顧客が自社組織を自己管理するためのOrganizations APIまで揃います。拡張はActions(認証フローの各ポイントにコードを差し込むサーバーレス関数)で行い、Universal Loginで一貫したログイン体験を提供します。

弱み。 機能が成熟している分、プレミアム価格になりやすい。Organizationsやエンタープライズ機能の可用性はプランや個別契約に依存し、上位は商談ベースです。小規模B2Cにはオーバースペックでコスト過大になりがち。

理想の場面。 顧客が大企業で「自社のIdPでログインさせろ」が当たり前の世界、テナント単位の管理・課金・ブランディングが必要なB2B SaaS。

4.3 Clerk — Next.js DXの王者

強み。 Next.jsとの統合が圧倒的です。clerkMiddleware()でルート保護を宣言的に書け、<SignIn /> <UserButton /> <OrganizationSwitcher />といったプリビルトUIで、認証画面を数分で本番品質に持っていけます。Organizations(B2B)、セッション管理、MFA、ボット対策、Webhookも揃い、B2C/B2Bの課金機能まで提供します。

弱み。 UI/SDKへの依存が深く、後から別基盤へ移すのは相応の作業になります。MAUが増えると料金は上がりやすく、B2BのSAML SSO等は上位/アドオン。データはClerk側にあり、データ主権要件には合いません。

理想の場面。 Next.jsでB2Cプロダクトやスタートアップを最短で立ち上げたいとき。「認証で消耗せず、プロダクトに集中したい」を最も叶えてくれます。

4.4 Supabase Auth — Postgres+RLSとの相乗効果

強み。 ユーザーはPostgresのauth.usersに格納され、発行されるJWTのクレーム(sub等)をRow Level Security(RLS)ポリシーで直接参照できます。つまり「認証」と「行レベルの認可」が同じDBの中で地続きになる。auth.uid()を使ったRLSで、アプリコードを書かずにテナント分離やユーザー単位のアクセス制御が実現します。パスワード、Magic Link、OTP、19以上のソーシャルプロバイダ、任意のOAuth2/OIDCプロバイダ連携に対応。OSSでフルセルフホスト可能な点はデータ主権の観点で大きい。

弱み。 SAML SSOはPro以上でSSO MAU課金。Cognito/Auth0ほどのエンタープライズ統合の厚みはまだなく、大規模ワークフォースSSOが主戦場なら設計上の工夫が要ります。

理想の場面。 すでにSupabase/Postgresを使う、RLSで認可を完結させたい、コストを抑えたい、将来セルフホストの逃げ道を残したいとき。


5. 実装スニペット

5.1 プロバイダ非依存のJWT検証ゲート(Next.js 16 ミドルウェア)

どの基盤を使っても、**「署名を検証したJWTだけを信用する」**のは共通の鉄則です。署名を検証せずクレームを読むのは、改ざんを受け入れるのと同じこと。ここではjoseでJWKS(公開鍵セット)から署名を検証する、最小のゲートを示します。RS256前提(Cognito等)で、公開鍵は発行者のJWKSエンドポイントから取得・キャッシュします。

// lib/auth/verify.ts
import { createRemoteJWKSet, jwtVerify, type JWTPayload } from "jose";

// 環境変数で発行者を切り替え(プロバイダ非依存)。
// Cognito: https://cognito-idp.<region>.amazonaws.com/<userPoolId>
const ISSUER = process.env.AUTH_ISSUER_URL!;
const AUDIENCE = process.env.AUTH_AUDIENCE; // Cognitoのaccess tokenはaud不在のためclient_idで別途検証

// JWKSはモジュールスコープでキャッシュ(リクエスト毎に再取得しない)。
const JWKS = createRemoteJWKSet(new URL(`${ISSUER}/.well-known/jwks.json`));

export async function verifyToken(token: string): Promise<JWTPayload> {
  // 署名・iss・exp・nbfを検証。失敗すれば例外。決して握りつぶさない。
  const { payload } = await jwtVerify(token, JWKS, {
    issuer: ISSUER,
    audience: AUDIENCE,
    algorithms: ["RS256"], // alg混同攻撃を防ぐため許可アルゴリズムを固定
  });
  return payload;
}
// proxy.ts(Next.js 16のミドルウェア。15以前は middleware.ts)
import { NextResponse, type NextRequest } from "next/server";
import { verifyToken } from "@/lib/auth/verify";

const PROTECTED = [/^\/app(?:\/|$)/, /^\/api\/(?!auth\/)/];

export async function proxy(req: NextRequest) {
  const needsAuth = PROTECTED.some((re) => re.test(req.nextUrl.pathname));
  if (!needsAuth) return NextResponse.next();

  // トークンはhttpOnly Cookieから読む(localStorageは使わない。後述)。
  const token = req.cookies.get("access_token")?.value;
  if (!token) return redirectToLogin(req);

  try {
    const claims = await verifyToken(token);
    // 検証済みクレームを下流へ。生トークンは渡さない。
    const headers = new Headers(req.headers);
    headers.set("x-user-id", String(claims.sub));
    return NextResponse.next({ request: { headers } });
  } catch {
    // 検証失敗=改ざん/失効/期限切れ。一律でログインへ。
    return redirectToLogin(req);
  }
}

function redirectToLogin(req: NextRequest) {
  const url = new URL("/login", req.url);
  url.searchParams.set("next", req.nextUrl.pathname);
  return NextResponse.redirect(url);
}

export const config = {
  matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
};

ポイントは3つ。(1) JWKSはキャッシュ(毎リクエストで公開鍵を取りに行かない)。(2) algorithmsを固定してalg: noneやHS256混同攻撃を封じる。(3) 検証例外は必ずログインへ倒す——「とりあえず通す」が最悪です。

5.2 プロバイダ固有例:Clerk(Next.js)

公式の作法に乗ると、検証ロジックは基盤側が引き受けてくれます。Clerkなら宣言的にこう書けます。

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

const isProtected = createRouteMatcher(["/app(.*)", "/api(.*)"]);

export default clerkMiddleware(async (auth, req) => {
  // protect()は未認証なら自動でサインインへリダイレクト。
  if (isProtected(req)) await auth.protect();
});

export const config = {
  matcher: [
    "/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|png|jpe?g|svg|woff2?)).*)",
    "/(api|trpc)(.*)",
  ],
};

5.1の手組みと比べると一目瞭然です。B2C/Next.jsでスピードが正義なら5.2、データ主権やマルチプロバイダ対応で抽象境界を自分で持ちたいなら5.1——この使い分けが選定そのものを映しています。


6. 移行(migration)の現実

「既存ユーザーをどう移すか」は、買い手が最も知りたいのに語られない論点です。ユーザーが10万人いれば、パスワードハッシュは移せない/移すべきでないという壁に必ずぶつかります。bcrypt等のハッシュは一方向で、平文は誰も持っていないからです。

現実的な戦略は次の3つです。

(1) Lazy migration(遅延移行)が本命。 新基盤に空のディレクトリを用意し、ユーザーが次にログインした瞬間に旧システムへ照合 → 成功したら新基盤にユーザーを作成、という流れにします。CognitoならUserMigration Lambdaトリガーがこの用途そのものです。

// Cognito UserMigration トリガー(Lazy migration)
import type { UserMigrationTriggerEvent } from "aws-lambda";
import { verifyAgainstLegacy } from "./legacy"; // 旧DBへの照合(外部入力として厳格に扱う)

export async function handler(
  event: UserMigrationTriggerEvent,
): Promise<UserMigrationTriggerEvent> {
  if (event.triggerSource === "UserMigration_Authentication") {
    // 旧システムでパスワードを検証。ここで初めて平文を扱える。
    const user = await verifyAgainstLegacy(event.userName, event.request.password);
    if (!user) throw new Error("Bad credentials"); // 認証失敗は曖昧なメッセージで

    // 検証できたら属性をCognitoへ移植。以後はCognitoが正となる。
    event.response.userAttributes = {
      email: user.email,
      email_verified: "true",
    };
    event.response.finalUserStatus = "CONFIRMED";
    event.response.messageAction = "SUPPRESS"; // 「ようこそ」メールを抑止
  }
  return event;
}

(2) Dual-run(並行稼働)でダウンタイムを避ける。 一斉切替(big bang)は事故ります。読み取りは新基盤、書き込みは両系——のように一定期間二重に動かし、移行率をメトリクスで監視しながら旧系を畳む。私がCognitoでエンタープライズSSOを設計した際も、フェデレーション経路を先に通し、ローカルユーザーをLazyに寄せる順序でダウンタイムをゼロに保つ設計を採りました。

(3) どうしてもハッシュごと移す場合。 Auth0など一部はbcryptハッシュのバルクインポートに対応します(同じアルゴリズム・コストである必要あり)。これが使えるなら一括移行も選べますが、対象アルゴリズムの制約を必ず確認してください。

移行で本当に守るべきは**「ユーザーにパスワード再設定を強制しない」**こと。それは離脱の最大要因です。Lazy migrationはこの体験を壊さずに移せる唯一の現実解です。


7. セキュリティ要点

認証基盤を「選んだ」だけでは安全になりません。実装の細部で決まります。

  • トークンの保管場所:httpOnly Cookie 一択。 access/refreshトークンをlocalStorageに置くと、XSS一発で全部抜かれます。httpOnly + Secure + SameSiteのCookieに入れ、JSから読めなくするのが基本。BFFパターン(ブラウザはCookieだけ持ち、トークンはサーバー側で扱う)にすればさらに堅い。
  • リフレッシュトークンのローテーション。 リフレッシュのたびに新しいリフレッシュトークンを発行し、旧トークンを無効化する(rotation)。加えてreuse detection——一度使われた古いトークンが再提示されたら「盗まれた」と判断し、そのファミリ全体を失効させる。
  • セッション失効(tokenVersionパターン)。 ステートレスJWTの弱点は「発行後の即時失効が難しい」こと。私がサブスクリプション基盤で採ったのは、ユーザーレコードにtokenVersion整数を持ち、JWTにも同じ値を埋める方式です。パスワード変更・不正検知・一括ログアウト時にtokenVersionをインクリメントすれば、既存トークンは検証時にバージョン不一致で全て無効化されます。DBの数値ひとつで「全デバイス即ログアウト」が効く、運用に効くパターンです。
// tokenVersionによる一括失効(検証側)
async function assertNotRevoked(claims: { sub: string; tokenVersion: number }) {
  const current = await getUserTokenVersion(claims.sub); // DBの現在値
  if (claims.tokenVersion !== current) {
    throw new Error("Session revoked"); // 不一致=失効済み。即拒否。
  }
}
  • アカウント列挙(account enumeration)防止。 「そのメールは登録されていません」と「パスワードが違います」を区別して返さない。サインアップやパスワードリセットでも、存在の有無を応答時間やメッセージで漏らさない(リセットは常に「送信しました」と返す)。OTPはHMAC-SHA256で署名・有効期限付き・試行回数制限を必ず付ける——これは私がサブスクリプション基盤のOTP(HMAC-SHA256)で実装した通りです。
  • 共通の原則。 すべての外部入力(IdPの主張、リダイレクトURL、ステート)を検証する。OIDCではPKCEとstate/nonce検証を省略しない。エラーは握りつぶさず、認証失敗は一律で曖昧なメッセージに倒す。

8. FAQ

Q. 結局、最初に問うべきことは何ですか? A. 「B2BかB2Cか」「データをどこに置く必要があるか」「既存のクラウド/DBは何か」の3つです。B2Bエンタープライズ+外部IdP連携ならAuth0かCognito、Next.js B2Cの速度重視ならClerk、Postgres/RLS前提ならSupabase——ここでほぼ決まります。

Q. 自作(roll-your-own)は本当にダメですか? A. ユーザーディレクトリやトークン署名・検証を丸ごと自作するのは勧めません。脆弱性の温床です。ただし、セッション失効やOTPのような「制御層」を、枯れたライブラリの上で薄く自作するのは現実的で、私もそうしています。責務を最小に切るのが条件です。

Q. MAU課金で予算が読めません。どう見積もればいい? A. 「アクティブの定義」と「上位機能(SSO/MFA/Organizations)が別課金か」を最初に確認してください。B2Cはユーザー数が線形に伸びるのでMAU単価が、B2Cと逆にB2Bはユーザー数より「テナント/SSO機能の単価」が効きます。無料枠の崖(突然の段階課金)も要チェックです。

Q. Cognitoはデザインの自由度が低いと聞きます。 A. ホスト型UIは確かに癖があります。割り切ってホスト型UIを使うか、Cognitoのユーザープール APIを直接叩いて自前UIを作るかの二択です。後者は自由ですが、その分セキュリティ実装の責任を自分で負います。

Q. SAML/OIDCに準拠していれば、後から乗り換えは簡単ですか? A. フェデレーション部分(外部IdP連携)はOIDC準拠なら比較的移しやすい一方、ユーザーディレクトリ・パスワード・独自フローへの依存が深いほど移行は重くなります。だからこそ§6のLazy migrationが効きます。標準準拠は「ロックインを下げる投資」と捉えてください。

Q. 一人+生成AIで、ここまでの認証基盤を本当に作れるのですか? A. 作れます。私は一人 × 生成AI(Claude Code)で開発を加速しつつ、認証のような重要領域には必ず人間の検証ゲートを置いています。署名検証・失効・列挙対策のテストを先に書き、AIが書いたコードをそのテストで縛る。速さと安全はトレードオフではなく、検証可能性で両立させます。


9. ご相談ください

認証基盤の選定・実装・移行は、「やり直しの効かない技術選定」です。私は経済産業大臣賞を受賞したB2B SaaSでCognitoによるエンタープライズSSO(RS256 JWT・OIDC/SAML)を、決済基盤でCognitoカスタム認証(Lambdaトリガー)を、サブスクリプション基盤でtokenVersion一括失効を備えたJWTセッション層を設計・実装してきました。

  • 選定:B2B/B2C・データ主権・コスト・既存スタックから、最適な基盤を比較レポートで提示します。
  • 実装:セキュアなトークン運用(httpOnly Cookie・ローテーション・失効)、SSO/MFA、RLS連携まで本番品質で。
  • 移行:Lazy migration・dual-runで、ユーザーにパスワード再設定を強制せず、ダウンタイムを出さない移行を設計します。

一人 × 生成AI(Claude Code)で、速く・安く・しかし検証ゲートを通して安全に。認証まわりでお困りなら、お気軽にご相談ください。

友田

友田 陽大

経済産業大臣賞 受賞プロダクト開発者。TypeScript + Python + AWS で、SaaS・業界DX・ 実用レベルの生成AI(RAG)を、要件定義からインフラ・運用まで一人で完遂します。

この記事で解説した技術の適用事例

経済産業大臣賞受賞 | 木材流通業界のDXを実現したB2BサブスクリプションSaaS

ケーススタディを見る