Auth.js(オースジェイエス)は、Webアプリにログイン機能を組み込むためのオープンソースの認証ライブラリです。前身はNext.js専用の「NextAuth.js」で、v5からNext.js以外のフレームワークにも対応する形でAuth.jsへ改称されました。この記事では、名前とパッケージの関係、v4とv5の違い、Next.js 16での導入手順、4つの認証方式の要件を2026年10月時点の公式ドキュメントとnpmの公開情報で整理します。さらに、Credentialsによるパスワードログイン、ロールでの画面とAPIの保護、Prisma Adapterでのデータベース保存、よく出るエラーの対処を、コピーして動かせるコードで示す構成です。最後に、2025年9月にBetter Authチームへ保守が移ったことと2026年7月に公開された脆弱性の修正版に触れ、今から採用してよいかを判断できるようにします。
まとめ:Auth.jsの要点(2026年10月時点)
- Auth.jsはNextAuth.jsの新しい名前です。Next.js向けのパッケージ名は今も
next-authで、SvelteKitやExpress向けは@auth/sveltekitなどの@auth/*パッケージになります。 - npmの安定版(latest)はv4系の
4.24.15、v5は5.0.0-beta.32で、v5は2023年10月の最初のベータから正式版になっていません(いずれも2026年7月20日公開。10月13日時点で更新なし)。 - v5ではルートの
auth.tsが返すauth()1つでServer Components・Route Handlers・Server Actionsのセッションを取得します。必須の環境変数はAUTH_SECRETだけです。 - Next.js 16では
middleware.tsがproxy.tsに改名されたため、公式手順もexport { auth as proxy }に変わっています。 - パスワードログインはCredentialsプロバイダで書けますが、ハッシュ化・保存・レート制限は自前です。ロールは
jwt・sessionコールバックでセッションへ載せ、ページとAPIの両方で確かめます。 - 2025年9月22日からBetter Authチームが保守しており、既存プロジェクトはそのまま使い続けられますが、新規プロジェクトにはBetter Authが強く推奨されています。
- 2026年7月20日に脆弱性4件が公開されました。
next-auth4.24.15/5.0.0-beta.32、@auth/core0.41.3 未満なら更新が必要です。
Auth.jsとは:NextAuth.jsから改称した認証ライブラリの正体
Auth.jsの読み方と「Auth」が指す認証・認可の役割の違い
Auth.jsは「オースジェイエス」と読みます。「Auth」はauthentication(認証=本人確認)の略で、ログインしている人が誰かを確かめるための処理です。何を許可するかを決めるauthorization(認可)とは区別されます。Auth.jsが担うのは主に前者で、ログイン・ログアウト・セッション維持と、その結果を使ったアクセス制御の土台です。認可の仕組みとして混同されやすいOAuthについてはOAuth 2.0とは?仕組み・認可フローと認証との違い、OAuth 2.1の変更点をわかりやすく解説で整理しています。
もとはNext.js専用の「NextAuth.js」として広まり、v5の開発でフレームワーク非依存の中核 @auth/core を切り出したことから、プロジェクト名がAuth.jsになりました。GitHubのリポジトリは今も nextauthjs/next-auth で、スター数は約2.8万(2026年10月時点)、ライセンスはISCです。
パッケージ構成:next-authと@auth/core・@auth/*の関係
「auth.js npm」で探すと複数のパッケージが見つかりますが、まずフレームワーク用パッケージを選び、認証方式に応じてDBアダプタや追加依存もインストールします。
| 用途 | パッケージ | 最新版(2026年10月) |
|---|---|---|
| Next.js(v4安定版) | next-auth | 4.24.15 |
| Next.js(v5) | next-auth@beta | 5.0.0-beta.32 |
| SvelteKit | @auth/sveltekit | 1.11.3 |
| Express | @auth/express | 0.12.3 |
| 中核ロジック | @auth/core | 0.41.3 |
| Prismaアダプタ | @auth/prisma-adapter | 2.11.3 |
| Drizzleアダプタ | @auth/drizzle-adapter | 1.11.3 |
公式の統合一覧では、SvelteKit・Express・SolidStart向けは「Experimental Release」の扱いです。@auth/core は各フレームワーク用パッケージの依存として入るもので、公式ドキュメントも「利用者が直接触る必要はない」としています。エラーのスタックトレースに「@auth/core」が表示された場合も、まず確認する対象は、利用中のフレームワーク用パッケージと、その依存バージョンです。SvelteKitでの使い方はSvelteKitとは?Svelteとの違い・始め方とv3の変更点で扱っています。
NextAuth.js v4とAuth.js v5の違い:設定場所とauth()の変更点
v5は設定の置き場所とセッションの取り出し方が変わる破壊的変更です。公式の移行ガイド(Migrating to v5)に載っている差分を表にまとめます。
| 項目 | v4(NextAuth.js) | v5(Auth.js) |
|---|---|---|
| 設定ファイル | APIルート内の設定(下記参照) | ルートの auth.ts |
| サーバーでのセッション取得 | getServerSession(引数は下記) | auth() |
| 環境変数の接頭辞 | NEXTAUTH_ | AUTH_ |
| Cookie名の接頭辞 | next-auth | authjs |
| DBアダプタ | @next-auth/*-adapter | @auth/*-adapter |
| 設定の型 | NextAuthOptions | NextAuthConfig |
| 対応Next.js | 12.2.5以降(16まで) | 14.0以降(16まで) |
表のv4の設定ファイルは pages/api/auth/[...nextauth].ts、サーバーでのセッション取得時の呼び出しは getServerSession(authOptions) です。実務で効くのは auth() への一本化です。v4では getServerSession・getSession・withAuth・getToken を場面ごとに使い分けていましたが、v5では auth.ts が返す auth 関数1つにまとまりました。呼び方は実行場所で変わり、Server Componentでは auth()、getServerSideProps では auth(ctx)、Pages RouterのAPI Routeでは auth(req, res) を使います。Route Handlerでは、auth でハンドラを包む書き方も選択可能です。AUTH_URL もほとんどの環境でリクエストヘッダから自動判定されるため、リバースプロキシの内側で動かすときに AUTH_TRUST_HOST=true を足す程度で済みます。App Routerのファイル規約はApp Routerとは?Next.jsのファイル規約・動的ルーティング・Pages Routerとの違いを参照してください。
4つの認証方式:OAuth・Email・Credentials・パスキーの要件
Auth.jsの認証方式は、外部サービスに任せるOAuth/OpenID Connect、メールのリンクでログインするEmail、自前のID・パスワードで照合するCredentials、パスキーを使うWebAuthnの4系統です。方式によってデータベースの要否とセッション方式の制約が違います。
| 方式 | DB | セッション | 状態 |
|---|---|---|---|
| OAuth/OIDC | 任意 | JWT/DB | 安定 |
| Email(マジックリンク) | 必須 | JWT/DB | 安定 |
| Credentials | 任意(自前) | JWTのみ | 安定 |
| WebAuthn(パスキー) | 必須(対応アダプタ) | JWT/DB | 実験的 |
OAuth・OpenID Connect:組み込みプロバイダと環境変数の自動推論
Google・GitHub・LINE・Microsoft Entra ID・Keycloak・Auth0など、組み込みプロバイダは100前後あります(packages/core/src/providers の定義ファイル数による)。v5では環境変数を AUTH_{プロバイダ名}_ID と AUTH_{プロバイダ名}_SECRET の形で置くと自動で読み込まれるため、providers: [GitHub] のようにプロバイダ関数を指定できます。別途、プロバイダ側でOAuthアプリとコールバックURLの登録が必要です。OpenID Connectの仕組みとIDトークンの検証はOIDC(OpenID Connect)とは?IDトークンの検証手順とOAuth 2.0との違いを解説で詳しく説明しています。
Email(マジックリンク)の要件:検証トークンを置くデータベース
メールアドレスに届いたリンクを踏むとログインできる方式で、送信にはResend・Nodemailer・SendGrid・Postmarkなどのプロバイダを使います。検証用トークンを保存する必要があるため、JWTセッションを選んだ場合でもデータベースアダプタの設定が必須です。公式ドキュメントも「データベースなしでEmailプロバイダを有効にすることはできない」と明記しています。
Credentials:JWTセッション限定でパスワードの管理は自前で持つ
既存の会員DBや社内の認証APIに、フォームで受け取ったID・パスワードを渡して照合する方式です。Auth.jsはパスワードのハッシュ化も保存もしないため、ソルト付きハッシュの生成と照合は authorize 関数の中で自分で書きます。また、Credentialsだけを使う構成でセッション方式を "database" にすると「Signing in with credentials only supported if JWT strategy is enabled」というエラーで止まります。既存の資産をつなぐ用途に限り、新規に作るならOAuthかパスキーを優先するのが無難です。具体的なコードは後述の「Credentialsでメールとパスワードのログインを実装する」で示します。
WebAuthn(パスキー):本番利用は推奨されない実験的な機能
パスキー用の Passkey プロバイダはありますが、公式ドキュメントは「実験的で本番利用は推奨しない」と警告しています。Passkeyプロバイダのページが挙げる最低バージョンは next-auth 5.0.0-beta.17、アダプタは @auth/prisma-adapter 1.3.3・@auth/unstorage-adapter 2.1.0・@auth/drizzle-adapter 1.1.1 で、Authenticator テーブルの追加と、設定の experimental: { enableWebAuthn: true } が要ります。本番でパスキーを必須にしたいなら、Auth.jsより対応が進んだ認証基盤を選ぶほうが確実です。パスキーの仕組み自体はFIDO認証・FIDO2とは?仕組みとパスキー・導入判断を解説を、登録と認証のフローをRP側で実装する手順はWebAuthnとは?パスキー認証を実装する仕組みと登録・認証フロー・RP実装の要点を参照してください。
Next.js 16にAuth.js v5を入れてGitHubログインを動かす手順
GitHubログインを例に、公式のInstallationページの手順で進めます。以下は、ルート直下にappディレクトリがあり、インポートエイリアスがプロジェクトルートを指すNext.jsのTypeScriptプロジェクトを前提にしています。Next.js 14・15でも手順は同じで、違うのは手順4のファイル名だけです。Next.js自体のプロジェクト作成から始める場合はNext.jsとは?16系App Routerで最小アプリを動かす手順と採用判断で雛形を用意してから戻ってきてください。
手順1:next-auth@betaのインストールとAUTH_SECRETの生成
npm install next-auth@beta
npx auth secret
npx auth secret は乱数のシークレットを生成し、Next.jsの場合は .env.local に AUTH_SECRET として書き込みます。この値はトークンとメール検証用ハッシュの暗号化に使われるため、環境ごとに別の値を使います。
手順2:GitHubのOAuthアプリ登録とコールバックURL・環境変数
GitHubのDeveloper settingsでOAuth Appを作り、Authorization callback URLに http://localhost:3000/api/auth/callback/github を登録します。発行されたClient IDとClient Secretを次の名前で置けば、コード側で読み込む処理は要りません。
AUTH_SECRET=(npx auth secret が書き込んだ値)
AUTH_GITHUB_ID=(Client ID)
AUTH_GITHUB_SECRET=(Client Secret)
手順3:ルートのauth.tsとapi/authのRoute Handlerを作成する
// auth.ts(プロジェクトのルート)
import NextAuth from "next-auth"
import GitHub from "next-auth/providers/github"
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [GitHub],
})
// app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/auth"
export const { GET, POST } = handlers
Route HandlerはApp Routerに置く必要がありますが、アプリの他の部分は pages/ のままでも動きます。
手順4:proxy.ts(Next.js 15以前はmiddleware.ts)を置く
// proxy.ts(Next.js 16)
export { auth as proxy } from "@/auth"
// middleware.ts(Next.js 15以前)
// export { auth as middleware } from "@/auth"
公式ドキュメント上は任意の手順で、アクセスのたびにセッションの有効期限を延ばす役割です。ファイル名の変更はNext.js側の仕様で、Next.jsのproxy.jsリファレンスに移行方法が載っています。ここで認可まで済ませる構成にすると、proxy(middleware)を迂回された場合にページが無防備になります。2025年3月に公開されたNext.jsのmiddleware迂回の脆弱性(CVE-2025-29927とは?Next.jsミドルウェア認可バイパスの影響範囲・修正版・検知方法)が実例で、保護したいページやServer Actionの中でも auth() を呼んで確かめる二重化が安全です。
手順5:ページでのセッション取得とログイン・ログアウトボタン
// app/page.tsx
import { auth, signIn, signOut } from "@/auth"
export default async function Page() {
const session = await auth()
if (!session?.user) {
return (
<form action={async () => { "use server"; await signIn("github") }}>
<button type="submit">GitHubでログイン</button>
</form>
)
}
return (
<form action={async () => { "use server"; await signOut() }}>
<p>{session.user.name} でログイン中</p>
<button type="submit">ログアウト</button>
</form>
)
}
npm run dev で起動して / を開き、GitHubの同意画面を経てユーザー名が表示されれば導入完了です。サーバー側のセッション取得には、v4・v5ともに SessionProvider は不要です。クライアントコンポーネントで useSession を使う場合だけ、SessionProvider で包みます。
Credentialsでメールとパスワードのログインを実装するコード例
社内システムや既存の会員DBをそのまま使いたい場合は、Credentialsプロバイダで自前の照合処理をつなぎます。公式のCredentialsページは、authorize がユーザーオブジェクトを返せばログイン成功、null を返せば失敗という約束と、入力値をサーバー側で必ず検証することを求めています。ここで示すのは、Zod 4系で入力を検証し、Node.js標準の scrypt でハッシュを照合する構成です。
入力検証のZodスキーマとscryptによるパスワード照合関数
// lib/zod.ts
import { z } from "zod"
export const signInSchema = z.object({
email: z.email(),
password: z.string().min(8).max(32),
})
// lib/user.ts(保存形式は "salt:hash" の16進文字列を想定)
import { scrypt, timingSafeEqual } from "node:crypto"
import { promisify } from "node:util"
import { prisma } from "@/prisma"
const scryptAsync = promisify(scrypt)
export async function verifyUser(email: string, password: string) {
const row = await prisma.user.findUnique({ where: { email } })
if (!row?.passwordHash) return null
const [salt, hash] = row.passwordHash.split(":")
const derived = (await scryptAsync(password, salt, 64)) as Buffer
const stored = Buffer.from(hash, "hex")
if (derived.length !== stored.length || !timingSafeEqual(derived, stored)) return null
return { id: row.id, email: row.email, name: row.name }
}
timingSafeEqual は比較にかかる時間からハッシュを推測されないための関数で、長さが違うと例外を投げるため先に長さをそろえて確かめます。passwordHash 列は自前で追加する列で、Auth.jsの標準スキーマには含まれません。Zodの書き方とZod 4での変更点はZodの使い方入門|npmでのインストールとz.infer・safeParse・Zod 4.6の変更点にまとめています。
// auth.ts
import NextAuth from "next-auth"
import Credentials from "next-auth/providers/credentials"
import { ZodError } from "zod"
import { signInSchema } from "@/lib/zod"
import { verifyUser } from "@/lib/user"
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
Credentials({
credentials: { email: {}, password: {} },
authorize: async (credentials) => {
try {
const { email, password } = await signInSchema.parseAsync(credentials)
return await verifyUser(email, password)
} catch (e) {
if (e instanceof ZodError) return null
throw e
}
},
}),
],
})
// app/login/actions.ts
"use server"
import { AuthError } from "next-auth"
import { signIn } from "@/auth"
export async function login(_prev: { error?: string } | undefined, formData: FormData) {
try {
await signIn("credentials", formData, { redirectTo: "/" })
} catch (e) {
if (e instanceof AuthError) return { error: e.type }
throw e
}
}
公式ドキュメントによれば、Server Actionから呼ぶ場合はログイン失敗がリダイレクトではなく CredentialsSignin の例外として投げられるため、上のように自分で捕捉します。成功時の signIn はリダイレクトのための例外を投げる仕組みです。そのため、AuthError 以外は必ず投げ直します。クライアント側では useActionState(login, undefined) で受け、state?.error があれば「メールアドレスかパスワードが違います」と表示します。どちらが違うのかを画面で区別しないのは、登録済みアドレスの探索を防ぐためです。Credentialsは既定でデータを保存せず、ログイン試行回数の制限やパスワードリセットも自前で用意する必要があります。
ロールで画面とAPIを守る:jwt・sessionコールバックと型拡張
管理画面だけを管理者に開く、といった認可は、ログイン時にユーザーのロールをセッションへ載せてから判定します。公式のロールベースアクセス制御ガイドの構成に沿って、JWTセッションの場合のコードを示します。
jwt・sessionコールバックでroleをセッションへ載せる設定
// auth.ts(NextAuth({...}) の中に追加)
callbacks: {
jwt({ token, user }) {
if (user) token.role = user.role // サインイン直後だけ user が渡る
return token
},
session({ session, token }) {
session.user.role = token.role
return session
},
authorized({ auth, request: { nextUrl } }) {
if (nextUrl.pathname.startsWith("/admin")) return auth?.user?.role === "admin"
return true
},
},
// types/next-auth.d.ts(tsconfig.json の include に入る場所ならどこでもよい)
import type { DefaultSession } from "next-auth"
declare module "next-auth" {
interface User { role?: string }
interface Session { user: { role?: string } & DefaultSession["user"] }
}
declare module "next-auth/jwt" {
interface JWT { role?: string }
}
型の拡張は公式のTypeScriptページの書き方で、DefaultSession["user"] と交差させて既定の項目を消さないようにします。authorized は proxy.ts から呼ばれ、false を返すとサインインページへ送られます。注意点として、JWTセッションではロールを変更しても、本人が再サインインするまでトークン内の値は古いままです。権限の剥奪をすぐ効かせたい場合は、後述のデータベースセッションにしてセッションコールバックで user.role を読む構成に切り替えます。トークンに何を入れてよいかの判断はJWTとは?構造・署名検証の仕組みとセッション・OAuth/OIDCとの違いを実装視点で解説が参考になります。
Route Handlerとproxy.tsのmatcherで保護範囲を指定する
// app/api/admin/route.ts
import { NextResponse } from "next/server"
import { auth } from "@/auth"
export const GET = auth(function GET(req) {
if (!req.auth) return NextResponse.json({ message: "Not authenticated" }, { status: 401 })
if (req.auth.user?.role !== "admin") return NextResponse.json({ message: "Forbidden" }, { status: 403 })
return NextResponse.json({ ok: true })
})
// proxy.ts(API と静的ファイルを対象から外す)
export { auth as proxy } from "@/auth"
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}
この2つは公式のProtecting Resourcesページの例をロール判定つきに広げたものです。matcherで api を除外しているため、APIの保護を担うのはRoute Handler側の判定だけです。未ログインは401、ログイン済みで権限が無い場合は403と分けておくと、フロント側でログイン画面へ送るか権限エラーを出すかを判断できます。公式も「proxyだけで認可せず、データを取得する場所の近くでセッションを確かめる」よう注意しており、Server ComponentやServer Actionの先頭でも auth() の結果を確認します。
Prisma Adapterでユーザーとセッションをデータベースに保存する
Emailやパスキーを使う場合、またはセッションを即時に失効させたい場合はDBアダプタを設定します。公式のPrisma Adapterページの手順は次のとおりです。
npm install @prisma/client @prisma/extension-accelerate @auth/prisma-adapter
npm install prisma --save-dev
// auth.ts
import NextAuth from "next-auth"
import { PrismaAdapter } from "@auth/prisma-adapter"
import { prisma } from "@/prisma"
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [],
})
prisma.ts では、開発サーバーのホットリロードで接続が増え続けないよう、PrismaClientを globalThis に1つだけ保持する書き方が公式に載っています。Prisma Postgres(Accelerate)を使わない場合は withAccelerate() の拡張を外してよい、というのが公式の注記です。スキーマは公式ページの User・Account・Session・VerificationToken の4モデル(パスキーを使うなら Authenticator も)を schema.prisma に貼り、npx prisma migrate dev でテーブルを作ります。ロールをDBで持つなら User に role String @default("user") を足し、セッションコールバックで user.role を返します。Prismaは7系でクライアントの生成先とDB接続の指定方法が変わっているため、手元の版に合わせた書き方はPrismaのバージョン完全ガイド|最新v7の変更点・確認方法とv6からの移行で確認してください。
セッション戦略:JWTセッションとデータベースセッションの選び方
アダプタを設定していなければJWTセッション、設定していればデータベースセッションが既定になります。どちらもセッション情報はHttpOnly Cookieで運ばれます。
- JWTセッション:トークンは署名だけでなく暗号化(JWE、
A256CBC-HS512)され、既定の有効期限は30日です。DBが要らない反面、ログアウト後もトークンを持っていれば期限まで有効で、途中で失効させるにはブロックリストを自前で持つ必要があります。Cookieが約4KBを超えると分割して送るため、トークンに多くの情報を詰めるとリクエストが重くなります。 - データベースセッション:Cookieにはセッションidだけを入れ、中身はDBに置きます。管理画面から特定ユーザーを即時ログアウトさせたい、権限変更をすぐ反映したいといった要件があるならこちらです。
DBアダプタを使うときはランタイムに注意します。Next.js 16の proxy.ts はNode.jsランタイムで動くため、この問題は起きません。Next.js 15以前の middleware.ts は既定でEdgeランタイムで動くので、Edge非対応のDBクライアントやドライバを読み込むとエラーになります。その場合、公式の移行ガイドはアダプタを含まない auth.config.ts と、アダプタを足す auth.ts に設定を分け、middleware側では前者だけを読み込み、セッション方式を "jwt" に固定する構成を紹介しています。JWTとBearerトークンの関係はBearer Token(ベアラートークン)とは?読み方・Authorization: Bearerの書き方とJWTとの違いが参照先です。
Auth.jsでよく出るエラーの原因と対処:MissingSecretなど6種
導入直後に止まりやすいエラーを、公式のエラーリファレンスの説明に沿って整理します。原因の切り分けには、設定に debug: true を足してサーバーログの [auth][debug] 行を見るのが近道です。
| エラー名 | 主な原因 | 対処 |
|---|---|---|
| MissingSecret | AUTH_SECRETが未設定 | npx auth secretで生成 |
| UntrustedHost | ホストを信頼する設定が無い | AUTH_TRUST_HOST=true |
| CredentialsSignin | authorizeが失敗した | Server Actionで捕捉 |
| AdapterError | アダプタのDB操作が失敗 | debug: trueで原因確認 |
| OAuthCallbackError | プロバイダがエラーを返した | コールバックURLを照合 |
| InvalidCallbackUrl | callbackUrlを検証できない | URL形式とCookieを確認 |
本番だけで出る代表は MissingSecret と UntrustedHost です。ローカルでは .env.local に値があっても、ホスティング側の環境変数に AUTH_SECRET を登録し忘れると起動直後に止まります。Auth.jsはリクエストヘッダのホスト値を信頼してURLを組み立てるため、自前のサーバーやコンテナの前にリバースプロキシを置く構成では、AUTH_TRUST_HOST=true の明示が必要です。OAuthCallbackError は、ユーザーが同意画面で拒否した場合のほか、プロバイダ側に登録したコールバックURLと実際のURL(ポート番号や末尾のパス)が一致しない設定ミスで起きます。
2026年にAuth.jsを採用すべきか:保守体制と脆弱性の判断材料
採用前には、保守体制、リリース状況、セキュリティ修正の提供状況を確認します。技術選定では次の3点を先に確認してください。
保守体制:2025年9月22日からBetter Authチームが担当
Better Authの公式ブログは2025年9月22日、Auth.jsの保守をBetter Authチームが引き継いだと発表しました。既存の利用者は中断なく使い続けられ、セキュリティパッチと緊急の不具合には対応を続けるとしています。一方で「新規プロジェクトは、特定の機能差がない限りBetter Authで始めることを強く推奨する」とも書いており、Auth.jsの公式ドキュメントにもBetter Authへの移行ガイドが追加されました。発表時点で機能差の代表例として挙げられていたのは、データベースを使わないステートレスなセッション管理でしたが、Better Authは2025年11月21日公開の1.4でDB不要のステートレスセッションに対応しています。npmのBetter Authは2026年10月時点で1.7系(1.7.7)が最新です。Better Auth側の機能と違いはbetter-authとは?Auth.jsとの違い・使い方とRedis・JWT対応を解説でまとめています。
Auth.js v5のリリース状況:約3年続くベータ版での提供
npmでは今も latest タグがv4系の4.24.15で、v5は beta タグの5.0.0-beta.32です。最初のベータ(5.0.0-beta.0)は2023年10月24日公開で、そこから約3年正式版が出ていません。authjs.devのドキュメントはv5以降を対象にしており、v4の資料は旧サイトのnext-auth.js.orgに残っています。v4を選ぶなら参照先を旧サイトに揃え、v5を選ぶならベータ版を本番に載せる前提で、更新のたびにリリースノートを確認する運用が要ります。
Auth.jsの脆弱性4件:2026年7月の公開内容と修正版
| ID | 深刻度 | 内容 |
|---|---|---|
| CVE-2026-73420 | High | マジックリンクが別の宛先へ届きうる |
| CVE-2026-73418 | High | 不正BearerヘッダでgetToken()が例外 |
| CVE-2026-73419 | Medium | OAuth検査Cookieと発行元の紐づけ欠如 |
| CVE-2026-73421 | Low | 設定エラー時に認証チェックが素通りする(v5のみ) |
表のOAuth検査Cookieは、state等の検査に使うCookieを指し、発行元に紐づかないという問題があります。構成エラーによる認証チェック迂回の修正版はnext-auth 5.0.0-beta.32のみです。他の3件の修正版は next-auth 4.24.15/5.0.0-beta.32、@auth/core 0.41.3です。各項目の詳細はGitHubのSecurity Advisoriesで確認できます。最も影響が大きいCVE-2026-73420は、Emailプロバイダを使い、既定のアドレス正規化のまま、Unicode正規化をかけるメール送信サービスを使っている場合に、攻撃者が被害者のアカウントで使えるログインリンクを自分の受信箱に届けさせられるというものです。Emailプロバイダを使っているなら最優先で更新してください。手元の版は次のコマンドで確かめられます。
npm ls next-auth @auth/core
npm install next-auth@beta # v5 の場合
npm install next-auth@4 # v4 の場合(4.24.15 以上が入る)
保守が移った後も、こうした修正は実際に出ています。
採用判断:既存は更新して継続、新規はBetter Authが第一候補
既にAuth.jsで動いているアプリは、修正版への更新と認証・認可の回帰確認を行い、現在の要件を満たすなら継続利用を選べます。移行ガイドも「今の構成がうまく動いているなら急いで移行する必要はない」としています。新規開発では、保守チーム自身が推奨するBetter Authを第一候補にするのが合理的です。DB不要のセッションもBetter Authの1.4で使えるようになったため、Auth.jsを新規で選ぶ理由は、既存のv4資産や社内の雛形とライブラリを揃えたい場合などに限られます。
逆に、ライブラリ選びより先に決めるべきことが残っているなら、そちらを優先します。社内のIdPとのSSO、複数システムでのアカウント統合、パスキー必須化、監査ログの保持期間といった要件は、Auth.jsとBetter Authのどちらを選んでも自前で設計する部分です。こうした認証基盤そのものの設計から相談したい場合は、一創の認証基盤・ID管理システム開発で、既存システムの棚卸しから移行計画まで対応しています。
よくある質問
Auth.jsの読み方は?
「オースジェイエス」と読みます。Authはauthentication(認証)の略です。
Auth.jsとNextAuth.jsは別のライブラリですか?
同じプロジェクトです。v5の開発でNext.js以外にも対応したためAuth.jsへ改称しました。Next.js向けのnpmパッケージ名は今も next-auth です。
Auth.jsは無料で使えますか?
ISCライセンスのオープンソースで、ライブラリ自体は無料です。費用がかかるのは、利用するDBやメール送信サービス、OAuthプロバイダ側の料金です。
Auth.jsでSAML認証(SSO)は使えますか?
SAMLを直接話す機能はありませんが、SAMLをOAuthに変換するBoxyHQ SAML(SAML Jackson)用のプロバイダが組み込まれており、これを経由して企業のIdPとつなげます。Microsoft Entra IDやOktaのようにOIDCで接続できるIdPなら、それぞれの組み込みプロバイダを使うほうが単純です。SAMLとOIDCの使い分けはSAMLとは?認証フロー・IdP/SPの仕組みとOAuth・OIDCとの使い分けを実装視点で解説で比較しています。
今からAuth.jsを使うならv4とv5のどちらですか?
新規ならv5(next-auth@beta)です。公式ドキュメントがv5前提で書かれており、Next.js 16の proxy.ts に対応した手順もv5にしかありません。ただし新規開発ではBetter Authも比較対象に入れてください。
関連記事
- better-authとは?Auth.jsとの違い・使い方とRedis・JWT対応を解説
- OIDC(OpenID Connect)とは?IDトークンの検証手順とOAuth 2.0との違いを解説
- OAuth 2.0とは?仕組み・認可フローと認証との違い、OAuth 2.1の変更点をわかりやすく解説
- JWTとは?構造・署名検証の仕組みとセッション・OAuth/OIDCとの違いを実装視点で解説
- CVE-2025-29927とは?Next.jsミドルウェア認可バイパスの影響範囲・修正版・検知方法
- App Routerとは?Next.jsのファイル規約・動的ルーティング・Pages Routerとの違い
- T3 Stackとは?構成技術・型安全の仕組み・メリット/デメリットと始め方