OSSの認証ライブラリ比較:Auth.js vs Lucia vs Better Auth でNext.jsにセキュアな認証を実装する
オープンソースラボ編集部 ・ 2026年6月14日
OSSの認証ライブラリ比較:Auth.js vs Lucia vs Better Auth でNext.jsにセキュアな認証を実装する
Clerk(月$25〜)・Auth0(月$23〜)・Firebase Auth(無料〜)に対して、Auth.js(NextAuth.js)(最も使われるOSSNext.js認証)・Lucia(軽量・シンプルな認証ライブラリ)・Better Auth(TypeScript特化・フル機能)はOSSの認証ライブラリです。
認証実装で押さえるべき要件
- セッション管理: JWTまたはDBセッションでユーザー状態を永続化
- OAuthプロバイダー統合: GitHub・Google・Twitter等のソーシャルログイン
- セキュリティ: CSRFトークン・セキュアCookie・HTTPS Only・レートリミット
- ロールベースアクセス: admin/user/guestの権限をMiddlewareでRoute保護
主要ツールの概要
Auth.js(NextAuth.js v5)
2020年に公開されたTypeScript製のOSSNext.js認証ライブラリです。GitHubスター25k+。Next.jsアプリの認証で最も使われているライブラウリで、70以上のOAuthプロバイダー(GitHub・Google・Spotify・Apple等)をサポート。v5からEdge RuntimeおよびNext.js App Routerにフル対応し、Adapter経由でPrisma・Drizzle・Supabase等のDBにセッションを保存できます。
# Auth.js v5 のインストール
npm install next-auth@beta @auth/drizzle-adapter
# または
npm install next-auth@beta @auth/prisma-adapter
// auth.ts - Auth.jsの設定(App Router)
import NextAuth from "next-auth";
import GitHub from "next-auth/providers/github";
import Google from "next-auth/providers/google";
import Credentials from "next-auth/providers/credentials";
import { DrizzleAdapter } from "@auth/drizzle-adapter";
import { db } from "@/lib/db";
import { users, accounts, sessions, verificationTokens } from "@/lib/schema";
import bcrypt from "bcryptjs";
export const { handlers, signIn, signOut, auth } = NextAuth({
adapter: DrizzleAdapter(db, {
usersTable: users,
accountsTable: accounts,
sessionsTable: sessions,
verificationTokensTable: verificationTokens,
}),
session: { strategy: "database" }, // DBセッション(JWT不使用)
providers: [
GitHub({
clientId: process.env.AUTH_GITHUB_ID!,
clientSecret: process.env.AUTH_GITHUB_SECRET!,
}),
Google({
clientId: process.env.AUTH_GOOGLE_ID!,
clientSecret: process.env.AUTH_GOOGLE_SECRET!,
}),
Credentials({
credentials: {
email: { label: "Email", type: "email" },
password: { label: "Password", type: "password" },
},
authorize: async (credentials) => {
if (!credentials?.email || !credentials?.password) return null;
const user = await db.query.users.findFirst({
where: (u, { eq }) => eq(u.email, credentials.email as string),
});
if (!user || !user.passwordHash) return null;
const valid = await bcrypt.compare(credentials.password as string, user.passwordHash);
if (!valid) return null;
return { id: user.id, email: user.email, name: user.name, role: user.role };
},
}),
],
callbacks: {
session: ({ session, user }) => ({
...session,
user: { ...session.user, id: user.id, role: user.role },
}),
},
pages: {
signIn: "/login",
error: "/login?error=true",
},
});
// app/api/auth/[...nextauth]/route.ts
export { GET, POST } from "@/auth";
export const runtime = "nodejs";
// middleware.ts - Route Protection(Middlewareで認証チェック)
import { auth } from "@/auth";
import { NextResponse } from "next/server";
export default auth((req) => {
const { pathname } = req.nextUrl;
const isLoggedIn = Boolean(req.auth?.user);
// 保護されたルート
const protectedRoutes = ["/dashboard", "/settings", "/admin"];
const isProtected = protectedRoutes.some((r) => pathname.startsWith(r));
if (isProtected && !isLoggedIn) {
const loginUrl = new URL("/login", req.url);
loginUrl.searchParams.set("callbackUrl", pathname);
return NextResponse.redirect(loginUrl);
}
// 管理者専用ルート
if (pathname.startsWith("/admin") && req.auth?.user?.role !== "admin") {
return NextResponse.redirect(new URL("/403", req.url));
}
return NextResponse.next();
});
export const config = {
matcher: ["/((?!api|_next|.*\..*).*)"],
};
// Server Componentでセッションを取得
import { auth } from "@/auth";
export default async function DashboardPage() {
const session = await auth();
if (!session) redirect("/login");
return (
<div>
<h1>ようこそ、{session.user.name}さん</h1>
<p>Role: {session.user.role}</p>
</div>
);
}
// Client Componentでセッションを取得
"use client";
import { useSession } from "next-auth/react";
export function UserButton() {
const { data: session, status } = useSession();
if (status === "loading") return <Skeleton />;
if (!session) return <SignInButton />;
return <Avatar user={session.user} />;
}
Better Auth
2024年に公開されたTypeScript製のOSSフル機能認証ライブラリです。GitHubスター10k+。Auth.jsよりもTypeScript型安全性が高く、メール/パスワード・OAuthプロバイダー・MFA(TOTP)・パスキー・組織/チームの多テナント・APIキー管理をセルフホストで実現。Clerk代替として機能が最も揃っています。
// auth.ts - Better Auth設定
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { twoFactor } from "better-auth/plugins";
import { organization } from "better-auth/plugins";
import { apiKey } from "better-auth/plugins";
import { db } from "@/lib/db";
export const auth = betterAuth({
database: drizzleAdapter(db, { provider: "pg" }),
emailAndPassword: {
enabled: true,
minPasswordLength: 12,
requireEmailVerification: true,
},
socialProviders: {
github: { clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET! },
google: { clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET! },
},
plugins: [
twoFactor(), // TOTP/2FAを有効化
organization(), // チーム・組織機能
apiKey(), // APIキー発行機能
],
session: {
cookieCache: { enabled: true, maxAge: 5 * 60 },
},
});
// auth-client.ts - クライアントサイドのSDK
import { createAuthClient } from "better-auth/react";
import { twoFactorClient } from "better-auth/client/plugins";
import { organizationClient } from "better-auth/client/plugins";
export const authClient = createAuthClient({
baseURL: process.env.NEXT_PUBLIC_APP_URL,
plugins: [twoFactorClient(), organizationClient()],
});
export const { signIn, signUp, signOut, useSession } = authClient;
機能比較表
| 比較項目 | Auth.js v5 | Lucia | Better Auth |
|---|---|---|---|
| OAuthプロバイダー | 70+ | 手動設定 | 主要10+ |
| メール/パスワード | ✅ | ✅ | ✅ |
| MFA/TOTP | ❌(別途実装) | ❌ | ✅ |
| 組織/チーム | ❌ | ❌ | ✅ |
| APIキー管理 | ❌ | ❌ | ✅ |
| Edge Runtime | ✅ | ✅ | ✅ |
| GitHub Stars | 25k+ | 5k+ | 10k+ |
認証後のユーザーデータをSupabaseで管理するにはDevOpsカテゴリ/categories/devopsのSupabase RLSと組み合わせてください。ログイン通知・異常検知アラートはCommunicationカテゴリ/categories/communicationのSlack Webhookと連携できます。
FAQ
Q. Auth.js v5(NextAuth.js)とClerkの違いは何ですか?
A. Clerk: クラウドサービス(ユーザーデータがClerkのサーバーに保存される)・UIコンポーネント付き(<SignIn>等すぐ使える)・無料枠10,000MAUまで・その後月$25〜。Auth.js: OSSライブラリ(ユーザーデータは自分のDBに保存)・UIは自分で作る必要がある・追加コストゼロ(インフラコストのみ)。GDPRやデータ主権の観点から「ユーザーデータを外部に出したくない」場合はAuth.jsの一択。開発速度を優先するスタートアップ初期はClerk、スケールして月$200+になった段階でAuth.jsに移行するパターンが多いです。
Q. Auth.jsでメールアドレス確認(Email Verification)を実装するには?
A. Resend(OSSメール送信SDK)またはNodemailerと組み合わせて実装できます。Auth.js v5ではsendVerificationRequestコールバックでカスタムメール送信処理を定義します。
import Resend from "next-auth/providers/resend";
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [
Resend({
apiKey: process.env.AUTH_RESEND_KEY,
from: "noreply@yourcompany.com",
}),
],
});
// /login でメールアドレスを入力するとMagic Linkを送信(パスワードレス)
Q. Better AuthのTOTP(2FA)をNext.jsに実装するには?
A. Better AuthのtwoFactorプラグインが最も簡単です。
// TOTPを有効化
const qrCode = await authClient.twoFactor.getTotpUri();
// QRコードをGoogle Authenticatorで読み取ってもらう
// TOTP検証
await authClient.twoFactor.verifyTotp({ code: "123456" });
Q. JWTセッションとDBセッションどちらを使うべきですか?
A. JWTセッション(stateless): ①全サーバーインスタンスがDBなしでトークンを検証できる(水平スケールが楽)②ログアウト時に即座に無効化できない(TTLが切れるまで有効)③ペイロードにユーザー情報を含めるため若干大きい。DBセッション(stateful): ①サーバーがDBにセッションを照会する(追加DBアクセスが発生)②ログアウト・強制無効化が即座に効く③セキュリティ要件が高い場合(医療・金融・社内ツール)に推奨。B2Cの一般向けWebサービスはJWT・B2Bやセキュリティ要件が高いサービスはDBセッションが一般的です。
まとめ
| ユースケース | 推奨ツール |
|---|---|
| Next.js社会ログイン・シンプル認証 | Auth.js v5 |
| 軽量・フレームワーク非依存・カスタム認証 | Lucia |
| Clerk代替・MFA・組織・APIキー全部入り | Better Auth |