AI

認証OSS比較:Auth.js vs Lucia vs BetterAuth でNext.jsに認証を実装する

オープンソースラボ編集部2026年6月13日

認証OSS比較:Auth.js vs Lucia vs BetterAuth でNext.jsに認証を実装する

Clerkは便利ですが月$25〜のコストがかかります。Auth.js(NextAuth v5)LuciaBetterAuthはNext.jsにOAuth・メール/パスワード・パスワードレス(マジックリンク)認証をOSSで実装できます。Supabase Authとの使い分けや、セッション管理・ロールベースアクセス制御(RBAC)の実装方法も解説します。

認証ライブラリが必要な場面

  • OAuth統合: Google・GitHub・Microsoft・LINEなど複数プロバイダーのソーシャルログインを実装したい
  • セッション管理: JWTとセッションCookieのどちらかを選んで安全にユーザー状態を管理したい
  • パスワードレス認証: メールのマジックリンクやWebAuthn(パスキー)でパスワードを廃止したい
  • RBAC: ユーザーの役割(admin・editor・viewer)によってアクセス可能なページを制限したい
  • 自社DB管理: ユーザーデータを自社のPostgreSQLに保存したい(Clerk・Auth0はSaaS)

主要ツールの概要

Auth.js(NextAuth v5)

Next.jsとの統合が最も充実したOAuth認証ライブラリです。GitHubスター24k+で、最も広く使われているNext.js認証ソリューションです。v5(旧NextAuth→Auth.js)でApp Router完全対応になりました。

// auth.ts - Auth.jsの設定
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";

export const { handlers, auth, signIn, signOut } = NextAuth({
  // Supabase PostgreSQLをアダプターとして使う
  adapter: DrizzleAdapter(db),

  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) => {
        const { email, password } = credentials as { email: string; password: string };
        const user = await db.query.users.findFirst({
          where: (u, { eq }) => eq(u.email, email),
        });
        if (!user) return null;
        const valid = await bcrypt.compare(password, user.passwordHash);
        if (!valid) return null;
        return { id: user.id, email: user.email, role: user.role };
      },
    }),
  ],

  callbacks: {
    // JWTにロールを追加
    jwt: async ({ token, user }) => {
      if (user) token.role = (user as any).role;
      return token;
    },
    session: async ({ session, token }) => {
      if (session.user) session.user.role = token.role as string;
      return session;
    },
  },

  pages: {
    signIn: "/login",
    error: "/login",
  },
});
// app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/auth";
export const { GET, POST } = handlers;

// middleware.ts - 認証が必要なルートを保護
import { auth } from "@/auth";
import { NextResponse } from "next/server";

export default auth((req) => {
  const isLoggedIn = !!req.auth;
  const isProtected = req.nextUrl.pathname.startsWith("/dashboard");

  if (isProtected && !isLoggedIn) {
    return NextResponse.redirect(new URL("/login", req.url));
  }
});

export const config = {
  matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};
// Server ComponentからセッションをGETする
import { auth } from "@/auth";

export default async function Dashboard() {
  const session = await auth();

  if (!session?.user) {
    redirect("/login");
  }

  return (
    <div>
      <h1>こんにちは、{session.user.name}さん</h1>
      <p>メール: {session.user.email}</p>
      <p>ロール: {session.user.role}</p>
    </div>
  );
}

Lucia

軽量で型安全なセッション管理ライブラリです。GitHubスター8k+。Auth.jsより低レベルで、セッションとユーザーの管理だけに集中した設計です。OAuth・パスワード・パスキーなどの認証メカニズムは自分で組み合わせます。

// lib/lucia.ts - Luciaの設定
import { Lucia } from "lucia";
import { DrizzlePostgreSQLAdapter } from "@lucia-auth/adapter-drizzle";
import { db, sessions, users } from "@/lib/db";
import { cookies } from "next/headers";
import { cache } from "react";

const adapter = new DrizzlePostgreSQLAdapter(db, sessions, users);

export const lucia = new Lucia(adapter, {
  sessionCookie: {
    attributes: {
      secure: process.env.NODE_ENV === "production",
    },
  },
  getUserAttributes: (attributes) => ({
    email: attributes.email,
    role: attributes.role,
    name: attributes.name,
  }),
});

// 現在のユーザーを取得するヘルパー(キャッシュあり)
export const validateRequest = cache(async () => {
  const sessionId = cookies().get(lucia.sessionCookieName)?.value ?? null;
  if (!sessionId) return { user: null, session: null };

  const { user, session } = await lucia.validateSession(sessionId);

  if (session?.fresh) {
    const sessionCookie = lucia.createSessionCookie(session.id);
    cookies().set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
  }

  if (!session) {
    const sessionCookie = lucia.createBlankSessionCookie();
    cookies().set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
  }

  return { user, session };
});
// app/api/login/route.ts - メール/パスワードログイン
import { lucia } from "@/lib/lucia";
import { db } from "@/lib/db";
import { cookies } from "next/headers";

export async function POST(req: Request) {
  const { email, password } = await req.json();

  const user = await db.query.users.findFirst({
    where: (u, { eq }) => eq(u.email, email),
  });

  if (!user || !await bcrypt.compare(password, user.passwordHash)) {
    return Response.json({ error: "Invalid credentials" }, { status: 401 });
  }

  // セッションを作成
  const session = await lucia.createSession(user.id, {});
  const sessionCookie = lucia.createSessionCookie(session.id);
  cookies().set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);

  return Response.json({ success: true });
}

BetterAuth

Next.js・Nuxt・SvelteKit等のフレームワークに対応した最新の認証ライブラリです。GitHubスター6k+で急成長中。Auth.jsより型安全で、プラグインアーキテクチャによる拡張性が高いです。

// lib/auth.ts - BetterAuthの設定
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { nextCookies } from "better-auth/next-js";
import { twoFactor, magicLink, passkey } from "better-auth/plugins";
import { db } from "./db";

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: "pg",
  }),

  plugins: [
    // 二段階認証(TOTP)
    twoFactor(),
    // マジックリンク(パスワードレス)
    magicLink({
      sendMagicLink: async ({ email, url }) => {
        await resend.emails.send({
          from: "auth@yoursite.com",
          to: email,
          subject: "ログインリンク",
          html: `<a href="${url}">こちらからログイン</a>`,
        });
      },
    }),
    // パスキー(WebAuthn)
    passkey(),
    // Cookieの設定(Next.js App Router用)
    nextCookies(),
  ],

  emailAndPassword: {
    enabled: true,
    requireEmailVerification: true,
    sendResetPassword: async ({ user, url }) => {
      await resend.emails.send({
        from: "auth@yoursite.com",
        to: user.email,
        subject: "パスワードリセット",
        html: `<a href="${url}">パスワードをリセット</a>`,
      });
    },
  },

  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!,
    },
  },
});

export type Session = typeof auth.$Infer.Session;
export type User = typeof auth.$Infer.Session.user;

機能比較表

比較項目Auth.js v5LuciaBetterAuth
ライセンスISCMITMIT
GitHub Stars24k+8k+6k+
OAuth対応✅ 70+プロバイダー✅ 手動実装✅ プラグイン
メール/パスワード
マジックリンク✅ プラグイン
パスキー(WebAuthn)✅ プラグイン
2FA/TOTP✅ プラグイン
セッション管理✅ Cookie/JWT✅ セッションDB
DBアダプター✅ Drizzle/Prisma等
型安全★★★☆☆★★★★☆★★★★★
App Router対応✅ v5から
RBAC✅ カスタム✅ カスタム
ドキュメント品質★★★★☆★★★☆☆★★★★☆

認証・アクセス制御ツールはsecurityカテゴリ(/categories/security)にまとめています。IDプロバイダーのセルフホストについてはKeycloak・Authentik比較(/categories/security)も参照してください。

FAQ

Q. Auth.js v4とv5(NextAuth→Auth.js)の違いは何ですか?

A. Auth.js v5(旧NextAuth v5)の主な変更点: ①App Router完全対応(Server Components・Server Actions・ミドルウェアでauth()を直接呼べる)、②設定ファイルがpages/api/auth/[...nextauth].tsauth.tsに一元化、③getServerSessionが不要になりawait auth()で統一、④プロバイダー名がGithubProviderGitHub等に短縮。v4からv5への移行は設定ファイルの書き換えとimportパスの変更が主で、ビジネスロジックへの影響は少ないです。Pages Routerとの後方互換性も一定維持されています。

Q. SupabaseのAuth機能とAuth.js/Luciaはどう使い分けますか?

A. Supabaseを使っているプロジェクトでは「Supabase Auth vs Auth.js」が悩みどころです。Supabase Authの優位点: ①Supabaseダッシュボードでユーザー管理ができる、②Row Level Security(RLS)と連携してDB行レベルのアクセス制御が簡単、③メール確認・パスワードリセットのUIが組み込み。Auth.js/Luciaの優位点: ①より細かなセッション管理・カスタムフィールドの自由度、②Supabase以外のDBに移行しやすい、③プロバイダー数が豊富。推奨: Supabaseをメインにしているなら「Supabase Auth + @supabase/ssr」が最もシームレスです。SupabaseをDBとして使いつつ認証を自分でコントロールしたいならAuth.jsを@auth/drizzle-adapterでSupabaseに接続します。

Q. JWTとセッションCookieのどちらを選ぶべきですか?

A. セッションCookie(DBセッション)推奨の場面: ①ユーザーセッションを即座に無効化したい(ログアウト・アカウント停止)、②セッションのメタデータ(最終ログイン・デバイス情報)を管理したい、③セキュリティが最優先(JWTは有効期限内は無効化不可)。JWT推奨の場面: ①完全ステートレスなAPIが必要(マイクロサービス間の認証)、②DBへのセッション検証コールを減らしたい(スケール重視)。Next.jsのWebアプリなら: ①セッションCookieを基本とし、②APIレートリミット・WebSocketでJWTを補助的に使うハイブリッド構成が安全でスケーラブルです。Auth.jsはデフォルトがJWTですがadapter設定でDBセッションに切り替えられます。

Q. BetterAuthのパスキー(WebAuthn)実装はどのくらい難しいですか?

A. BetterAuthのパスキー(passkey)プラグインを使えば比較的簡単に実装できます。サーバー側: plugins: [passkey()]を追加するだけ。クライアント側: @simplewebauthn/browserがBetterAuthに同梱されており、signIn.passkey()を呼ぶだけでブラウザのパスキー認証ダイアログが開きます。難しい点: ①本番環境ではHTTPS必須(localhostは例外)、②RP ID(Relying Party ID)をドメインに合わせて設定する必要がある、③iOSのSafariとAndroidのChromeで動作確認が必要(実装の癖が異なる)。パスキーはパスワードレスで最もセキュアな認証方式として普及が進んでいます。

まとめ

ユースケース推奨ツール
OAuth + シンプルなNext.js認証Auth.js v5
セッション管理を細かく制御Lucia
2FA・パスキー・マジックリンクを全部使いたいBetterAuth
Supabaseと連携Supabase Auth + @supabase/ssr

関連外部リソース

他の記事も読む

Let's Build Together

OSS導入、自社だけで悩まない。

ツール選定から構築・運用・AI活用まで、オープンソースラボ運営元のClasslessが伴走します。初回のご相談は無料です。