個人開発で認証が必要な理由と基礎知識
なぜ個人開発でも認証が必須なのか
「とりあえずログインなしで作って、あとから追加すればいいか」—— この判断が個人開発の最大の技術的負債になることは珍しくありません。 認証が必要な理由は3つあります。
- ユーザーデータの保護義務: 個人情報保護法により、ユーザーのデータを扱うサービスでは適切なアクセス制御が法的に求められます。 たとえ個人開発であっても、メールアドレスを収集する時点で対象になります。
- 収益化の前提条件: 課金機能(Stripe連携)、プレミアム機能の制限、ユーザーごとのデータ保存—— これらはすべて「誰がアクセスしているか」を識別する認証が前提です。 ShiftB受講生のうち収益化に成功した38サービスの全てが認証を実装していました。
- 後付けのコストは3倍: ShiftBの開発支援データによると、認証を後から追加した場合の平均工数は初期実装の約3.2倍。データベース設計の変更、既存APIの改修、 テストのやり直しが発生するためです。
認証(Authentication)と認可(Authorization)の違い
認証ライブラリを選ぶ前に、2つの概念を正確に理解しておきましょう。 混同すると、実装の方向性を見誤ります。
| 概念 | 認証(Authentication) | 認可(Authorization) |
|---|
| 問い | 「あなたは誰ですか?」 | 「あなたは何ができますか?」 |
| 具体例 | ログイン、メール認証、OAuth | 管理者のみ編集可、有料会員限定 |
| 実装場所 | 認証ライブラリが担当 | アプリケーションコード + RLS |
| タイミング | リクエストの最初 | 認証の後 |
この記事では主に認証を扱いますが、認可も含めた設計パターンにも触れます。 特にSupabase AuthのRLS(Row Level Security)は、認証と認可を統合的に扱える強力な機能です。
認証方式の種類 — セッション vs JWT vs マネージド
認証の内部実装は大きく3つの方式に分かれます。 ライブラリ選定の判断基準になるので、特徴を押さえておきましょう。
| 方式 | 仕組み | メリット | デメリット | 代表ライブラリ |
|---|
| セッションベース | サーバー側にセッション情報を保存し、CookieでセッションIDをやり取り | 即座にセッション無効化が可能 | サーバーに状態を持つ(スケーリング注意) | Auth.js(デフォルト) |
| JWTベース | 署名付きトークンをクライアント側で保持し、サーバーは検証のみ | サーバーレスと相性が良い | トークン無効化が即座にできない | Supabase Auth, Better Auth |
| マネージドサービス | 認証のUIとロジックをすべて外部サービスに委譲 | 実装量が最小。UI込みで提供 | ベンダーロックイン。料金が高め | Clerk, Firebase Auth |
個人開発では、Vercelにデプロイする前提ならJWTベースかマネージドサービスが相性が良いです。 セッションベースはサーバーレス環境でRedis等の外部ストアが必要になるケースがあるためです。

【2026年版】認証ライブラリ5大比較 — Auth.js / Supabase Auth / Clerk / Firebase Auth / Better Auth
Auth.js(NextAuth.js v5)— 最も歴史のあるOSS認証ライブラリ
Auth.js(旧NextAuth.js)は、Next.jsエコシステムで最も長い歴史を持つ認証ライブラリです。 2020年のリリース以来、GitHub Starは25,000超。v5でApp Router/Server Componentsに 完全対応し、Edge Runtimeでも動作するようになりました。
特徴:
- 80以上のOAuthプロバイダーに対応(Google、GitHub、Discord等)
- データベースアダプター(Prisma、Drizzle、Supabase等)が豊富
- セッション管理をJWTとデータベースの両方から選べる
- 完全無料(OSSライセンス)
- TypeScript完全対応
向いているケース:コストをゼロに抑えたい、カスタマイズ性を重視する、複数のOAuthプロバイダーを使いたい
注意点:UIコンポーネントは自前で作る必要がある。v4→v5の移行は破壊的変更が多く、既存記事の情報が古いケースが多い
Supabase Auth — バックエンドと認証を統合するBaaS
Supabase Authは、SupabaseプラットフォームのAuth機能として提供される認証サービスです。データベース(PostgreSQL)と認証が同じプラットフォームに統合されている点が最大の強みです。
特徴:
- RLS(Row Level Security)との統合で、認証と認可を一元管理
- メール/パスワード、OAuth、Magic Link、電話番号認証に対応
- 月間アクティブユーザー(MAU)50,000人まで無料
- Next.jsの
@supabase/ssrパッケージで公式サポート - ユーザー管理ダッシュボードが標準搭載
向いているケース:バックエンドにSupabaseを使う場合(認証+DB+ストレージが一元管理できる)、RLSでセキュリティを強化したい場合
注意点:Supabase以外のバックエンドと組み合わせるメリットは薄い。UIコンポーネントは自前か@supabase/auth-ui-reactを使用
Clerk — 認証UIごとまるっとお任せできるマネージドサービス
Clerkは、認証に必要なUI(ログインフォーム、ユーザープロフィール、組織管理)をすべて提供するマネージドサービスです。2021年のリリース以降急成長し、 2025年にはシリーズCで5,000万ドルを調達しています。
特徴:
- ログイン/サインアップUIがプリビルド(カスタマイズ可)
- 多要素認証(MFA)、パスキー対応が標準
- 組織(Organization)管理、招待機能が組み込み
- Webhook連携でユーザー作成時にDBと自動同期
- MAU 10,000人まで無料
向いているケース:認証UIの開発時間を最小化したい、B2B SaaSで組織管理が必要、MFA/パスキーを簡単に導入したい
注意点:無料枠を超えるとMAUあたり$0.02の従量課金。デザインのカスタマイズに限界がある場合もある
Firebase Auth — Googleエコシステムの認証サービス
Firebase AuthはGoogleが提供する認証サービスで、最も利用者が多い認証プラットフォームのひとつです。 ただし、2026年現在はNext.js App Routerとの相性に課題があります。
特徴:
- Google、Apple、Microsoftなど主要プロバイダー対応
- 電話番号認証(SMS)が標準搭載
- Firebase全体(Firestore、Cloud Functions等)との統合
- MAU制限なし(Sparkプラン)で基本無料
- 匿名認証で段階的なユーザー登録が可能
向いているケース:既にFirebase(Firestore)をバックエンドに使っている、モバイルアプリ(React Native/Flutter)との共通認証が必要
注意点:Next.js App Router(Server Components)での利用にハック的なコードが必要になりがち。クライアントサイドSDKが前提の設計で、SSRとの相性に課題あり
Better Auth — 2025年に登場した新世代のOSS認証
Better Authは2025年にリリースされたTypeScriptファーストの認証ライブラリです。 Auth.jsの課題(設定の複雑さ、型安全性)を解決することを目指して開発されました。 GitHub Starは急速に伸び、2026年4月時点で22,000超です。
特徴:
- TypeScriptの型推論が完全に効く設計
- プラグインシステムで機能を柔軟に拡張
- Drizzle ORM、Prismaとネイティブ統合
- 2FA、パスキー、組織管理もプラグインで追加
- 完全無料(OSSライセンス)
向いているケース:TypeScriptの型安全性を最大限活用したい、Auth.jsの設定に不満がある、最新技術をキャッチアップしたい
注意点:新しいライブラリのため、ドキュメント・日本語情報がまだ少ない。本番採用事例もAuth.jsほど豊富ではない
5大認証ライブラリ総合比較表
| 比較項目 | Auth.js v5 | Supabase Auth | Clerk | Firebase Auth | Better Auth |
|---|
| 種別 | OSS | BaaS | マネージド | マネージド | OSS |
| 無料枠 | 完全無料 | MAU 50,000 | MAU 10,000 | 実質無制限 | 完全無料 |
| UI提供 | なし(自前) | 部分的 | フル提供 | 部分的 | なし(自前) |
| App Router対応 | 完全 | 完全 | 完全 | 部分的 | 完全 |
| Server Components | 対応 | 対応 | 対応 | 要ワークアラウンド | 対応 |
| OAuth対応数 | 80+ | 20+ | 30+ | 15+ | 50+ |
| MFA/パスキー | 手動実装 | MFAのみ | 標準搭載 | MFAのみ | プラグイン |
| DB統合 | アダプター | PostgreSQL統合 | Webhook | Firestore | アダプター |
| 学習コスト | 中 | 低〜中 | 低 | 中 | 中 |
| 日本語ドキュメント | 豊富 | やや豊富 | 増加中 | 豊富 | 少ない |
AI時代のアプリ開発コース
ShiftBのAIシフトコースは、Claude Codeで本格的なWebアプリケーションを作りながらAI駆動開発を身につけるコースです。ただ作って終わりではなく、コードを読め、セキュリティに責任を持って提案でき、要件定義などの上流工程まで担えるところまで現役エンジニアがサポートします。
AIシフトコースを見る →料金・コスト徹底比較 — MAU別の月額シミュレーション
個人開発の認証コストはゼロで始められる
「認証にお金をかけたくない」は個人開発者の正直な気持ちです。 良いニュースは、5つすべてのライブラリが無料で始められることです。 ただし、ユーザーが増えたときのコストは大きく異なります。
MAU別・月額料金シミュレーション
実際にユーザーが増えた場合のコストを試算しました。 個人開発でよくある4つのフェーズで比較します。
| MAU | Auth.js v5 | Supabase Auth | Clerk | Firebase Auth | Better Auth |
|---|
| 100人(MVP期) | $0 | $0 | $0 | $0 | $0 |
| 1,000人(初期成長期) | $0 | $0 | $0 | $0 | $0 |
| 10,000人(成長期) | $0 | $0 | $0 | $0 | $0 |
| 50,000人(スケール期) | $0 | $0 | $800/月〜 | $0 | $0 |
| 100,000人 | $0 | $25/月〜(Proプラン) | $1,800/月〜 | $0(電話SMS除く) | $0 |
注目ポイント:
- Auth.jsとBetter AuthはOSSのためユーザー数に関係なく無料。ただし、インフラ費(Vercel、DB等)は別途必要
- Supabase Authは無料枠がMAU 50,000と寛大。ほとんどの個人開発サービスは無料枠に収まる
- Clerkは10,000MAUを超えると急激にコストが上がる。ただし、UI開発工数を節約できる分、開発者の時間単価と天秤にかける必要がある
- Firebase Authは認証単体のコストは低いが、Firestore等の利用で間接コストが発生しやすい
「開発コスト」も含めた本当のコスト比較
月額料金だけを見ると OSSが最安に見えますが、開発時間のコストも考慮すべきです。 ShiftB受講生の実装時間データから試算します。
| 作業項目 | Auth.js v5 | Supabase Auth | Clerk |
|---|
| 初期セットアップ | 2〜3時間 | 1〜2時間 | 30分〜1時間 |
| ログインUI開発 | 4〜6時間 | 3〜5時間 | 0時間(プリビルド) |
| プロフィール画面 | 2〜3時間 | 2〜3時間 | 0時間(プリビルド) |
| エラーハンドリング | 2〜3時間 | 1〜2時間 | 0.5時間 |
| 合計 | 10〜15時間 | 7〜12時間 | 1〜2時間 |
時給3,000円で換算すると、Auth.jsは3〜4.5万円、Clerkは3,000〜6,000円の開発コスト。 MAU 10,000人以下の個人開発なら、Clerkの月額料金は無料なので、開発コストの差がそのまま「本当のコスト差」になります。

Next.js App Routerで認証を実装する実践チュートリアル
前提環境と完成イメージ
ここからは、Next.js 15 + App Router環境で、 実際に認証を実装する手順を解説します。 ShiftBの受講生が最も多く採用しているSupabase Authを例に、 以下の機能を実装します。
- メール/パスワードでの新規登録・ログイン
- GoogleのOAuthログイン
- ログイン状態に応じたページ表示の切り替え
- Server ComponentsとClient Componentsでのセッション取得
- Middlewareによるルート保護
所要時間の目安:約2〜3時間(Next.jsの基礎知識がある前提)
Step 1: Supabaseプロジェクトの作成とパッケージインストール(10分)
まず、Supabaseのダッシュボードで新規プロジェクトを作成します。 次に、必要なパッケージをインストールします。
npm install @supabase/supabase-js @supabase/ssr
環境変数をプロジェクトの.env.localに設定します。 値はSupabaseダッシュボードの Settings > API から取得できます。
NEXT_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6...
Step 2: Supabaseクライアントの作成(15分)
Next.js App Routerでは、Server Components用とClient Components用で異なるSupabaseクライアントが必要です。@supabase/ssrがこれを簡単にしてくれます。
Server Components用(lib/supabase/server.ts):
import { createServerClient } from "@supabase/ssr";
import { cookies } from "next/headers";
export async function createClient() {
const cookieStore = await cookies();
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return cookieStore.getAll();
},
setAll(cookiesToSet) {
try {
cookiesToSet.forEach(({ name, value, options }) =>
cookieStore.set(name, value, options)
);
} catch {
// Server Componentでは書き込み不可(正常動作)
}
},
},
}
);
}
Client Components用(lib/supabase/client.ts):
import { createBrowserClient } from "@supabase/ssr";
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
}
Step 3: Middlewareでセッションをリフレッシュ(15分)
Next.jsのMiddlewareで、すべてのリクエストでセッショントークンをリフレッシュします。 これにより、期限切れのトークンが自動的に更新されます。
// middleware.ts
import { createServerClient } from "@supabase/ssr";
import { NextResponse, type NextRequest } from "next/server";
export async function middleware(request: NextRequest) {
let supabaseResponse = NextResponse.next({ request });
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return request.cookies.getAll();
},
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value, options }) => {
request.cookies.set(name, value);
supabaseResponse.cookies.set(name, value, options);
});
},
},
}
);
const { data: { user } } = await supabase.auth.getUser();
// 未ログインユーザーを保護されたルートからリダイレクト
if (!user && request.nextUrl.pathname.startsWith("/dashboard")) {
const url = request.nextUrl.clone();
url.pathname = "/login";
return NextResponse.redirect(url);
}
return supabaseResponse;
}
export const config = {
matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
};
Step 4: ログイン・サインアップページの実装(30分)
メール/パスワード認証とGoogle OAuthの両方に対応したログインページを作ります。
// app/login/page.tsx
"use client";
import { createClient } from "@/lib/supabase/client";
import { useState } from "react";
import { useRouter } from "next/navigation";
export default function LoginPage() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [isSignUp, setIsSignUp] = useState(false);
const [error, setError] = useState("");
const router = useRouter();
const supabase = createClient();
const handleEmailAuth = async (e: React.FormEvent) => {
e.preventDefault();
setError("");
const { error } = isSignUp
? await supabase.auth.signUp({ email, password })
: await supabase.auth.signInWithPassword({ email, password });
if (error) {
setError(error.message);
return;
}
router.push("/dashboard");
router.refresh();
};
const handleGoogleLogin = async () => {
await supabase.auth.signInWithOAuth({
provider: "google",
options: {
redirectTo: `${location.origin}/auth/callback`,
},
});
};
return (
<div className="mx-auto max-w-md p-8">
<h1 className="mb-6 text-2xl font-bold">
{isSignUp ? "新規登録" : "ログイン"}
</h1>
<button
onClick={handleGoogleLogin}
className="mb-4 w-full rounded-lg border p-3"
>
Googleでログイン
</button>
<form onSubmit={handleEmailAuth} className="space-y-4">
<input
type="email"
placeholder="メールアドレス"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full rounded-lg border p-3"
required
/>
<input
type="password"
placeholder="パスワード(8文字以上)"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="w-full rounded-lg border p-3"
minLength={8}
required
/>
{error && <p className="text-red-500 text-sm">{error}</p>}
<button
type="submit"
className="w-full rounded-lg bg-blue-600 p-3 text-white"
>
{isSignUp ? "新規登録" : "ログイン"}
</button>
</form>
<button
onClick={() => setIsSignUp(!isSignUp)}
className="mt-4 text-sm text-blue-600 underline"
>
{isSignUp
? "アカウントをお持ちの方はこちら"
: "新規登録はこちら"}
</button>
</div>
);
}
Step 5: OAuth Callbackルートの実装(10分)
Google OAuth認証のコールバックを処理するRoute Handlerを作成します。
// app/auth/callback/route.ts
import { createClient } from "@/lib/supabase/server";
import { NextResponse } from "next/server";
export async function GET(request: Request) {
const { searchParams, origin } = new URL(request.url);
const code = searchParams.get("code");
const next = searchParams.get("next") ?? "/dashboard";
if (code) {
const supabase = await createClient();
const { error } = await supabase.auth.exchangeCodeForSession(code);
if (!error) {
return NextResponse.redirect(`${origin}${next}`);
}
}
return NextResponse.redirect(`${origin}/login?error=auth_failed`);
}
Step 6: Server Componentsでのユーザー情報取得(10分)
ダッシュボードページなど、Server Componentsでログインユーザーの情報を表示します。
// app/dashboard/page.tsx
import { createClient } from "@/lib/supabase/server";
import { redirect } from "next/navigation";
export default async function DashboardPage() {
const supabase = await createClient();
const { data: { user } } = await supabase.auth.getUser();
if (!user) redirect("/login");
return (
<div className="p-8">
<h1 className="text-2xl font-bold">ダッシュボード</h1>
<p className="mt-4">
ようこそ、{user.email} さん
</p>
</div>
);
}
ポイント:getUser()は毎回Supabaseサーバーにリクエストを送り、 トークンの有効性を検証します。getSession()はローカルのJWTを読むだけなので高速ですが、セキュリティ上重要な処理には必ずgetUser()を使ってください。
AI時代のアプリ開発コース
ShiftBのAIシフトコースは、Claude Codeで本格的なWebアプリケーションを作りながらAI駆動開発を身につけるコースです。ただ作って終わりではなく、コードを読め、セキュリティに責任を持って提案でき、要件定義などの上流工程まで担えるところまで現役エンジニアがサポートします。
AIシフトコースを見る →個人開発の認証セキュリティ対策チェックリスト
個人開発でも最低限やるべきセキュリティ対策
「個人開発だからセキュリティは後回し」は絶対にNGです。 ユーザーのパスワードやメールアドレスが漏洩した場合、法的責任を問われる可能性があります。 ただし、すべてを自前で実装する必要はありません。 以下のチェックリストの上6項目は認証ライブラリが自動で処理してくれます。
認証ライブラリが自動で守ってくれること
| セキュリティ対策 | Auth.js | Supabase Auth | Clerk | Better Auth |
|---|
| パスワードのハッシュ化(bcrypt/Argon2) | アダプター依存 | 自動 | 自動 | 自動 |
| CSRF対策 | 自動 | 自動 | 自動 | 自動 |
| セッション/トークン管理 | 自動 | 自動 | 自動 | 自動 |
| XSS対策(HttpOnly Cookie) | 自動 | 自動 | 自動 | 自動 |
| レート制限(ブルートフォース対策) | 手動 | 自動 | 自動 | 手動 |
| メール確認(Email Verification) | 手動 | 自動 | 自動 | プラグイン |
開発者が自分で実装すべきセキュリティ対策
以下の対策は認証ライブラリが自動でやってくれないため、開発者自身が実装する必要があります。
- 環境変数の管理:
.env.localは絶対にGitにコミットしない。.gitignoreに含まれていることを確認。Vercelの環境変数設定を使う - 認可(Authorization)の実装:「ログインしているか」だけでなく 「このユーザーがこのデータにアクセスしてよいか」をチェック。SupabaseならRLSを必ず有効化
- APIルートの保護:すべてのAPI Route Handler/Server Actionで
getUser()によるユーザー検証を行う - 入力値のバリデーション:メールアドレスの形式チェック、 パスワード強度の検証をサーバー側でも実施
- エラーメッセージの注意:「メールアドレスが存在しません」ではなく 「メールアドレスまたはパスワードが正しくありません」と表示。 ユーザーの存在を推測させない
良い実装 vs 悪い実装の具体例
悪い例:API Routeでユーザー検証をスキップ
// ❌ 悪い例:誰でもアクセスできてしまう
export async function POST(request: Request) {
const { userId, data } = await request.json();
// userIdをリクエストボディから信頼してしまっている
await db.update(users).set(data).where(eq(users.id, userId));
return Response.json({ success: true });
}
良い例:Server側でユーザーを検証してからデータ更新
// ✅ 良い例:認証されたユーザーのみアクセス可能
export async function POST(request: Request) {
const supabase = await createClient();
const { data: { user } } = await supabase.auth.getUser();
if (!user) {
return Response.json({ error: "Unauthorized" }, { status: 401 });
}
const { data } = await request.json();
// user.idはサーバー側で取得した信頼できる値
await db.update(users).set(data).where(eq(users.id, user.id));
return Response.json({ success: true });
}
認証実装でよくある失敗パターンと対策
失敗1: 認証ライブラリを途中で乗り換える
ShiftB受講生で最も時間をロスしたケースが、開発途中での認証ライブラリ変更です。 ある受講生はFirebase Authで開発を進めた後、Server Componentsとの相性問題で Supabase Authに乗り換え、約25時間の手戻りが発生しました。
対策:この記事の比較表を参考に、開発を始める前に技術選定を済ませる。 迷ったらShiftBの推奨構成(Supabase Auth + Next.js App Router)を選べば間違いない
失敗2: getSession()をセキュリティに依存させる
getSession()はクライアントのJWTを読み取るだけで、サーバー側での検証は行いません。つまり、改ざんされたトークンでも そのまま信頼してしまいます。
対策:データの変更や機密情報の表示には、必ずgetUser()を使う。getSession()は表示の切り替え(UIの出し分け)など、 セキュリティリスクが低い処理にのみ使用する
失敗3: 認証なしでMVPを作り、後から追加しようとする
「まずは認証なしで動くものを作ろう」という判断は一見合理的ですが、 実際にはデータモデル全体の設計が変わってしまうため、 手戻りのコストが大きくなります。
対策:MVPであっても、認証は最初に実装する。 Step 1〜6のチュートリアルなら2〜3時間で完了するので、 「後回し」にするほどの工数ではない
失敗4: パスワードリセット機能を忘れる
リリース後に「パスワードを忘れたのですが…」というユーザーからの問い合わせで 気づくパターンです。ShiftB受講生の約23%が初回リリースで パスワードリセット機能を実装し忘れていました。
対策:認証実装のチェックリストに「パスワードリセット」を必ず含める。 Supabase AuthとClerkなら、ほぼ設定だけで実装可能
失敗5: 本番環境でOAuthのリダイレクトURLを設定し忘れる
ローカルでは動くのに本番で「redirect_uri_mismatch」エラーになる、 という報告が非常に多いです。Google CloudコンソールやSupabaseダッシュボードで、本番ドメインのリダイレクトURLを登録し忘れるのが原因です。
対策:デプロイ前チェックリストに「OAuth設定のリダイレクトURL確認」を入れる。 Vercelのプレビューデプロイ用URLも忘れずに登録する
個人開発フェーズ別・認証ライブラリ選定フローチャート
パターンA: 「とにかく最速でリリースしたい」→ Clerk
ハッカソン、MVP検証、プロトタイプなど、スピード最優先の場面では Clerkが最適です。ログインUI、プロフィール画面、組織管理がすべてプリビルドされているため、 認証に関する開発時間を1〜2時間に圧縮できます。
推奨ケース:
- 初めての個人開発で認証の実装に自信がない
- 2週間以内にMVPをリリースしたい
- B2B SaaSで組織管理が必要
パターンB: 「バックエンドもまとめて構築したい」→ Supabase Auth
データベース・認証・ストレージをひとつのプラットフォームで統合管理したい場合、 Supabase Authが最適です。ShiftBの受講生で最も採用率が高い(82%)構成でもあります。
推奨ケース:
- Next.js + Supabaseの技術スタックを使う予定
- RLS(Row Level Security)でデータのアクセス制御をしたい
- 将来的にMAU 50,000人以上を目指すが、初期コストを抑えたい
パターンC: 「コスト完全ゼロ+カスタマイズ自由」→ Auth.js / Better Auth
OSSでコストを完全にゼロに抑えたい、または認証のロジックを 完全にコントロールしたい場合はAuth.jsまたはBetter Authが適しています。
推奨ケース:
- Prisma / DrizzleでDBを自前管理している
- 80以上のOAuthプロバイダーを使いたい(Auth.js)
- TypeScriptの型安全性を最大限活かしたい(Better Auth)
- マネージドサービスに依存したくない
パターンD: 「モバイルアプリと共通の認証」→ Firebase Auth
React Native / Flutterでモバイルアプリも開発する予定がある場合は、 Firebase AuthがWeb・iOS・Androidで共通のユーザー管理を提供します。
推奨ケース:
- Webアプリとモバイルアプリの両方を開発予定
- 既にFirestoreをバックエンドに使っている
- 電話番号認証(SMS)が必要

よくある質問(FAQ)
Q1. プログラミング初心者でも認証を実装できますか?
はい、可能です。特にClerkを使えば、コードを数行書くだけでログイン機能が動きます。 ただし、認証が「何をしているのか」の基本概念(この記事のH2-1)は理解しておくことを推奨します。 理由は、トラブル発生時に原因の切り分けができないと解決に時間がかかるからです。
Q2. Auth.jsとBetter Auth、OSSならどちらがおすすめ?
2026年4月時点では、Auth.js v5を推奨します。理由は3つです。 1つ目は日本語の情報が圧倒的に多いこと。2つ目はv5でApp Routerに完全対応し、安定していること。 3つ目は本番採用事例が豊富で、エッジケースの対処法が蓄積されていること。 Better Authは設計思想が優れていますが、まだ情報と採用事例が少ないため、 「困ったときに自力で解決できる」中上級者向けです。
Q3. Supabase AuthとClerk、迷っています。決め手は?
最大の判断基準は「バックエンドにSupabaseを使うかどうか」です。 Supabaseをバックエンド(DB、ストレージ)に使うなら、認証もSupabase Authで統一するのが合理的です。 RLSとの統合で、認証と認可をシームレスに管理できます。 一方、バックエンドが別(Prisma + 自前DBなど)の場合は、Clerkの方がセットアップが速く、 UIも提供されるため効率的です。
Q4. バイブコーディング(AIコーディング)で認証を実装しても安全ですか?
認証ライブラリの利用コードであれば、問題ありません。 Claude CodeやCursorに「Supabase Authでログイン機能を実装して」と指示すれば、 公式ドキュメントに基づいた正しいコードを生成してくれます。 ただし、認証ロジックを自前で書かせるのは危険です。 パスワードのハッシュ化やトークン生成は、必ず認証ライブラリの機能を使ってください。 ShiftBでは「認証は自前で実装しない」を鉄則として教えています。
Q5. 将来的にライブラリを乗り換えることになったらどうすれば?
完全に避けることは難しいですが、影響を最小限にする設計はできます。 具体的には、認証関連のコードをlib/auth/のような単一ディレクトリに集約し、 アプリケーションコードからは抽象化されたインターフェース(getCurrentUser()など) 経由でアクセスする設計にします。こうすれば、乗り換え時に変更するファイルが限定されます。
Q6. 無料プランから始めて、ユーザーが増えたらプラン変更できますか?
はい、すべてのサービスで無料プランからの段階的なアップグレードが可能です。 Supabase Authは無料枠(MAU 50,000)からProプラン($25/月)への移行が管理画面から1クリック。 Clerkも同様にプランのアップグレードが可能です。データの移行は不要で、 プランを変更するだけで利用可能なMAU数が増えます。
Q7. 認証の実装が不安です。ShiftBではどう教えていますか?
ShiftBでは、Supabase Auth + Next.js App Routerの構成を標準カリキュラムで教えています。 受講生はメンターのサポートを受けながら、認証の基礎概念から実装、デプロイまでを約3時間のワークショップで完了しています。 「ライブラリの選定で迷っている」「セキュリティが不安」という方は、 まず無料相談会でお気軽にご相談ください。