auth-js について
Auth.js v5 の設定とトラブルシューティングを案内する開発スキルです。Next.js または Cloudflare Workers で認証を実装する開発者やコーディングエージェント向けに、設定例、セッション方式、よくある問題をまとめています。
主な機能
- 01Next.js と Workers の設定手順
- 02JWT とデータベースセッションの説明
- 03OAuth、Credentials、Magic Link に対応
- 04アダプターとデータベースの設定
- 05よくあるエラーと対処の要点
活用シーン
- 01Next.js アプリのサインインとセッション設定
- 02Cloudflare Workers への認証機能のデプロイ
- 03実行環境に合ったセッション方式の選択
- 04コールバック、エッジ実行環境、デプロイの問題調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jackspace/ claudeskillz --skill auth-jsインストール後、Claude Code で/auth-jsを入力して読み込まれたか確認します。
同梱ファイルREADME.mdSKILL.json
詳細
Auth.js v5 認証スタック
本番環境での検証済み:複数の Next.js および Cloudflare Workers プロジェクト 最終更新日:2025-10-26 ステータス:本番環境対応 ✅ 公式ドキュメント:https://authjs.dev
⚠️ 始める前に(必ずお読みください!)
AI エージェントにとって重要:Auth.js のセットアップをユーザーに支援する Claude Code の場合:
- 会話の最初に、このスキルを使用していることを明確に伝えてください
- 一般的な知識ではなく、このスキルのパターンを参照してください
references/common-errors.mdに記載されている既知の問題を防いでください- 推測しないでください。不明な場合はスキルのドキュメントを確認してください
ユーザーの操作が必要です:まずこのスキルを確認するよう Claude に伝えてください!
次のように伝えます:「Auth.js を設定しています。まず auth-js スキルを確認してください」
これが重要な理由(実際の結果)
スキルを有効にしない場合:
- ❌ セットアップ時間:約15分
- ❌ 発生するエラー:3~5件(AUTH_SECRET、CallbackRouteError、エッジ関連の問題)
- ❌ 必要な手動修正:3~4回のコミット
- ❌ トークン使用量:約15k
- ❌ ユーザーの信頼度:複数回のデバッグセッションが必要
スキルを有効にした場合:
- ✅ セットアップ時間:約3分
- ✅ 発生するエラー:0件
- ✅ 必要な手動修正:0件
- ✅ トークン使用量:約6k(60%削減)
- ✅ ユーザーの信頼度:すぐに成功
このスキルで防げる既知の問題
- AUTH_SECRET がない → JWEDecryptionFailed エラー
- CallbackRouteError → authorize() 内で例外をスローし、null を返さない
- ルートが見つからない → [...nextauth].js のファイルパスが正しくない
- エッジとの互換性がない → エッジ互換のアダプターなしでデータベースセッションを使用
- PKCE エラー → OAuth プロバイダーの設定ミス
- セッションが更新されない → ミドルウェアがない
- v5 への移行に関する問題 → 名前空間の変更、JWT ソルトの変更
- D1 バインディングエラー → Wrangler の設定の不一致
- データベースを使用した認証情報 → セッション戦略との互換性がない
- 本番環境へのデプロイ失敗 → 環境変数がない
- トークンの更新エラー → コールバックの実装が正しくない
- JSON を期待しているのに HTML が返される → Next.js 15 の rewrites 設定
これらはすべて、スキルが有効なときに自動で対処されます。
目次
- クイックスタート - Next.js
- クイックスタート - Cloudflare Workers
- 基本概念
- セッション戦略
- プロバイダーの設定
- データベースアダプター
- ミドルウェアのパターン
- 高度な機能
- 重要なルール
- よくあるエラーと修正方法
- テンプレートのリファレンス
クイックスタート:Next.js
前提条件
# Next.js 15+ with App Router
npm create next-app@latest my-app
cd my-app
インストール
npm install next-auth@latest
npm install @auth/core@latest
# Choose your database adapter (if using database sessions)
npm install @auth/prisma-adapter # For PostgreSQL/MySQL
npm install @auth/d1-adapter # For Cloudflare D1
1. Auth の設定を作成する
オプション A:シンプルな設定(JWT セッション、データベースなし)
// auth.ts
import NextAuth from "next-auth"
import GitHub from "next-auth/providers/github"
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [
GitHub({
clientId: process.env.AUTH_GITHUB_ID,
clientSecret: process.env.AUTH_GITHUB_SECRET,
}),
],
})
オプション B:エッジ互換の設定(ミドルウェアでの使用に推奨)
// auth.config.ts (edge-compatible, no database)
import type { NextAuthConfig } from "next-auth"
import GitHub from "next-auth/providers/github"
export default {
providers: [
GitHub({
clientId: process.env.AUTH_GITHUB_ID,
clientSecret: process.env.AUTH_GITHUB_SECRET,
}),
],
} satisfies NextAuthConfig
// auth.ts (full config with database)
import NextAuth from "next-auth"
import { PrismaAdapter } from "@auth/prisma-adapter"
import { PrismaClient } from "@prisma/client"
import authConfig from "./auth.config"
const prisma = new PrismaClient()
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
session: { strategy: "jwt" }, // CRITICAL: Force JWT for edge compatibility
...authConfig,
})
2. API ルートハンドラーを作成する
// app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/auth"
export const { GET, POST } = handlers
3. ミドルウェアを追加する(任意ですが推奨)
// middleware.ts
export { auth as middleware } from "@/auth"
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}
4. 環境変数
# .env.local
AUTH_SECRET=your-secret-here # Generate with: npx auth secret
AUTH_GITHUB_ID=your_github_client_id
AUTH_GITHUB_SECRET=your_github_client_secret
# CRITICAL: In production, AUTH_SECRET is REQUIRED
5. コンポーネントで使用する
サーバーコンポーネント(App Router):
import { auth } from "@/auth"
export default async function Dashboard() {
const session = await auth()
if (!session?.user) {
return <p>Not authenticated</p>
}
return <p>Welcome {session.user.name}</p>
}
クライアントコンポーネント:
"use client"
import { useSession } from "next-auth/react"
export default function ClientDashboard() {
const { data: session, status } = useSession()
if (status === "loading") return <p>Loading...</p>
if (status === "unauthenticated") return <p>Not authenticated</p>
return <p>Welcome {session?.user?.name}</p>
}
6. サインイン/サインアウト
import { signIn, signOut } from "@/auth"
export function SignIn() {
return (
<form
action={async () => {
"use server"
await signIn("github")
}}
>
<button type="submit">Sign in with GitHub</button>
</form>
)
}
export function SignOut() {
return (
<form
action={async () => {
"use server"
await signOut()
}}
>
<button type="submit">Sign Out</button>
</form>
)
}
クイックスタート:Cloudflare Workers
前提条件
npm create cloudflare@latest my-auth-worker
cd my-auth-worker
インストール
npm install @auth/core@latest
npm install @auth/d1-adapter@latest
npm install hono
1. D1 を使用して Wrangler を設定する
// wrangler.jsonc
{
"name": "my-auth-worker",
"main": "src/index.ts",
"compatibility_date": "2025-10-26",
"d1_databases": [
{
"binding": "DB",
"database_name": "auth_db",
"database_id": "your-database-id"
}
]
}
2. D1 データベースを作成する
# Create database
npx wrangler d1 create auth_db
# Copy the database_id to wrangler.jsonc
# Create tables
npx wrangler d1 execute auth_db --file=./schema.sql
schema.sql:
-- See templates/cloudflare-workers/schema.sql for complete schema
CREATE TABLE users (
id TEXT PRIMARY KEY,
name TEXT,
email TEXT UNIQUE NOT NULL,
emailVerified INTEGER,
image TEXT
);
CREATE TABLE accounts (
id TEXT PRIMARY KEY,
userId TEXT NOT NULL,
type TEXT NOT NULL,
provider TEXT NOT NULL,
providerAccountId TEXT NOT NULL,
refresh_token TEXT,
access_token TEXT,
expires_at INTEGER,
token_type TEXT,
scope TEXT,
id_token TEXT,
session_state TEXT,
FOREIGN KEY (userId) REFERENCES users(id) ON DELETE CASCADE,
UNIQUE(provider, providerAccountId)
);
CREATE TABLE sessions (
id TEXT PRIMARY KEY,
userId TEXT NOT NULL,
expires INTEGER NOT NULL,
sessionToken TEXT UNIQUE NOT NULL,
FOREIGN KEY (userId) REFERENCES users(id) ON DELETE CASCADE
);
CREATE TABLE verification_tokens (
identifier TEXT NOT NULL,
token TEXT UNIQUE NOT NULL,
expires INTEGER NOT NULL,
PRIMARY KEY (identifier, token)
);
3. Auth を備えた Worker を作成する
// src/index.ts
import { Hono } from 'hono'
import { Auth } from '@auth/core'
import { D1Adapter } from '@auth/d1-adapter'
import GitHub from '@auth/core/providers/github'
type Bindings = {
DB: D1Database
AUTH_SECRET: string
AUTH_GITHUB_ID: string
AUTH_GITHUB_SECRET: string
}
const app = new Hono<{ Bindings: Bindings }>()
app.all('/api/auth/*', async (c) => {
const response = await Auth(c.req.raw, {
adapter: D1Adapter(c.env.DB),
providers: [
GitHub({
clientId: c.env.AUTH_GITHUB_ID,
clientSecret: c.env.AUTH_GITHUB_SECRET,
}),
],
secret: c.env.AUTH_SECRET,
trustHost: true,
})
return response
})
app.get('/', async (c) => {
// Example: Get session
const session = await Auth(c.req.raw, {
adapter: D1Adapter(c.env.DB),
providers: [],
secret: c.env.AUTH_SECRET,
})
return c.json({ session })
})
export default app
4. 環境変数
# Add secrets to Cloudflare Workers
npx wrangler secret put AUTH_SECRET
npx wrangler secret put AUTH_GITHUB_ID
npx wrangler secret put AUTH_GITHUB_SECRET
5. デプロイする
npx wrangler deploy
基本概念
セッション戦略
Auth.js v5 は、2 つのセッション戦略をサポートしています。
-
JWT(JSON Web Token) - アダプターが設定されていない場合のデフォルト
- ✅ エッジランタイムで動作します
- ✅ セッションのデータベースクエリが不要です
- ✅ 高速でスケーラブルです
- ❌ サーバー側でセッションを無効化できません
- ❌ トークンサイズに制限があります
-
データベース - アダプターが設定されている場合のデフォルト
- ✅ セッションを完全に制御できます(無効化、延長)
- ✅ データベースに監査証跡を残せます
- ✅ トークンサイズに制限がありません
- ❌ リクエストごとにデータベースクエリが必要です
- ❌ すべてのエッジランタイムと互換性があるわけではありません
選択マトリックス:
| ユースケース | 推奨される戦略 | 理由 |
|---|---|---|
| Next.js App Router | JWT | エッジランタイムとの互換性 |
| Cloudflare Workers | JWT またはデータベース(D1 使用) | D1 はエッジと互換性があります |
| 従来の Node.js | データベース | セッションを完全に制御できます |
| 高いセキュリティが必要 | データベース | セッションを無効化できます |
| 読み取り専用セッション | JWT | データベースのオーバーヘッドがありません |
詳しい比較については、references/session-strategies.md を参照してください。
セッション戦略
JWT セッション(デフォルト)
使用する状況:
- エッジランタイムにデプロイする場合(Cloudflare Workers、Vercel Edge)
- データベースアダプターが設定されていない場合
- セッションデータが読み取り専用の場合
- トラフィックの多いアプリケーションの場合(DB クエリが不要)
設定:
export const { handlers, auth } = NextAuth({
session: {
strategy: "jwt",
maxAge: 30 * 24 * 60 * 60, // 30 days
},
providers: [GitHub],
})
⚠️ 重要: アダプターを設定している場合でも、エッジランタイムとの互換性を確保するには strategy: "jwt" を明示的に設定する必要があります!
データベースセッション
使用する状況:
- Node.js ランタイム(エッジではない)
- サーバー側でセッションを無効化する必要がある場合
- コンプライアンス要件がある場合(監査証跡)
- セッションデータが JWT の制限を超える場合
設定:
import { PrismaAdapter } from "@auth/prisma-adapter"
export const { handlers, auth } = NextAuth({
adapter: PrismaAdapter(prisma),
session: {
strategy: "database",
maxAge: 30 * 24 * 60 * 60,
updateAge: 24 * 60 * 60, // Update session every 24 hours
},
providers: [GitHub],
})
⚠️ エッジランタイムの制限:
アダプターがエッジと互換性がない場合、エッジランタイム(ミドルウェア)ではデータベースセッションを使用できません。設定を分割してください。
// auth.config.ts (edge-compatible)
export default {
providers: [GitHub],
} satisfies NextAuthConfig
// auth.ts (full config with database)
import authConfig from "./auth.config"
export const { handlers, auth } = NextAuth({
adapter: PrismaAdapter(prisma), // Not edge-compatible
session: { strategy: "jwt" }, // FORCE JWT for middleware
...authConfig,
})
プロバイダーの設定
OAuth プロバイダー(GitHub、Google など)
GitHub:
import GitHub from "next-auth/providers/github"
export const { handlers, auth } = NextAuth({
providers: [
GitHub({
clientId: process.env.AUTH_GITHUB_ID,
clientSecret: process.env.AUTH_GITHUB_SECRET,
}),
],
})
Google(トークン更新あり):
import Google from "next-auth/providers/google"
export const { handlers, auth } = NextAuth({
providers: [
Google({
clientId: process.env.AUTH_GOOGLE_ID,
clientSecret: process.env.AUTH_GOOGLE_SECRET,
authorization: {
params: {
prompt: "consent",
access_type: "offline",
response_type: "code",
},
},
}),
],
})
完全な例については、templates/providers/oauth-github-google.ts を参照してください。
Credentials プロバイダー(メールアドレス/パスワード)
⚠️ 重要: Credentials プロバイダーがサポートするのは JWT セッションのみです!
import Credentials from "next-auth/providers/credentials"
import { z } from "zod"
import bcrypt from "bcryptjs"
const signInSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
})
export const { handlers, auth } = NextAuth({
providers: [
Credentials({
credentials: {
email: { label: "Email", type: "email" },
password: { label: "Password", type: "password" },
},
authorize: async (credentials) => {
try {
const { email, password } = await signInSchema.parseAsync(credentials)
// Fetch user from database
const user = await db.user.findUnique({ where: { email } })
if (!user || !user.password) {
// CRITICAL: Return null, DON'T throw
return null
}
const passwordMatch = await bcrypt.compare(password, user.password)
if (!passwordMatch) {
return null
}
// Return user object
return {
id: user.id,
email: user.email,
name: user.name,
}
} catch (error) {
// CRITICAL: Return null on error, DON'T throw
console.error("Auth error:", error)
return null
}
},
}),
],
})
⚠️ 重要なルール:
authorize()では決してエラーをスローしないでください。常にnullを返してください- 理由: エラーをスローすると、
CredentialsSigninではなくCallbackRouteErrorが発生します - 認証情報を確認する前に、必ず Zod で検証してください
- パスワードは bcrypt でハッシュ化し、平文で保存しないでください
完全な例については、templates/providers/credentials.ts を参照してください。
Magic Link プロバイダー(パスワードレス)
⚠️ 重要: Magic Link にはデータベースアダプターが必須です!
import Resend from "next-auth/providers/resend"
import { PrismaAdapter } from "@auth/prisma-adapter"
export const { handlers, auth } = NextAuth({
adapter: PrismaAdapter(prisma), // REQUIRED
providers: [
Resend({
apiKey: process.env.AUTH_RESEND_KEY,
from: "[email protected]",
}),
],
})
完全な例については、templates/providers/magic-link-resend.ts を参照してください。
データベースアダプター
Cloudflare D1 アダプター
インストール:
npm install @auth/d1-adapter@latest
Wrangler の設定:
// wrangler.jsonc
{
"d1_databases": [
{
"binding": "DB",
"database_name": "auth_db",
"database_id": "your-database-id"
}
]
}
使用方法:
import { D1Adapter } from "@auth/d1-adapter"
// Cloudflare Workers
const app = new Hono<{ Bindings: { DB: D1Database } }>()
app.all('/api/auth/*', async (c) => {
return await Auth(c.req.raw, {
adapter: D1Adapter(c.env.DB),
providers: [GitHub],
})
})
// Next.js (with D1 via wrangler)
export const { handlers, auth } = NextAuth({
adapter: D1Adapter(env.DB),
session: { strategy: "jwt" }, // Recommended for edge
providers: [GitHub],
})
データベーススキーマ:
完全なスキーマについては、templates/cloudflare-workers/schema.sql を参照してください。
エッジとの互換性: ✅ D1 は完全にエッジと互換性があります!
Prisma アダプター(PostgreSQL/MySQL)
インストール:
npm install @auth/prisma-adapter@latest
npm install @prisma/client@latest
npm install -D prisma@latest
Prisma スキーマ:
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(cuid())
name String?
email String @unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
}
model Account {
id String @id @default(cuid())
userId String
type String
provider String
providerAccountId String
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
userId String
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model VerificationToken {
identifier String
token String @unique
expires DateTime
@@unique([identifier, token])
}
使用方法:
import { PrismaAdapter } from "@auth/prisma-adapter"
import { PrismaClient } from "@prisma/client"
const prisma = new PrismaClient()
export const { handlers, auth } = NextAuth({
adapter: PrismaAdapter(prisma),
session: { strategy: "jwt" }, // For edge compatibility
providers: [GitHub],
})
エッジとの互換性: ❌ Prisma はデフォルトではエッジと互換性がありません
回避策: エッジとの互換性を確保するには Prisma Accelerate または Hyperdrive を使用するか、JWT セッションを強制し、ミドルウェアではアダプターを使用しないでください。
完全な例については、templates/database-adapters/prisma-postgresql.ts を参照してください。
ミドルウェアのパターン
セッションの有効期限を延長
// middleware.ts
export { auth as middleware } from "@/auth"
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}
これにより、すべてのリクエストでセッションの有効期限が自動的に更新されます。
ルートの保護
// middleware.ts
import { auth } from "@/auth"
import { NextResponse } from "next/server"
export default auth((req) => {
const { pathname } = req.nextUrl
// Protect /dashboard routes
if (pathname.startsWith("/dashboard")) {
if (!req.auth) {
const loginUrl = new URL("/login", req.url)
loginUrl.searchParams.set("callbackUrl", pathname)
return NextResponse.redirect(loginUrl)
}
}
return NextResponse.next()
})
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}
ロールベースのアクセス制御(RBAC)
// auth.ts
export const { handlers, auth } = NextAuth({
providers: [GitHub],
callbacks: {
async jwt({ token, user }) {
// Add role to JWT on sign in
if (user) {
token.role = user.role
}
return token
},
async session({ session, token }) {
// Expose role to session
if (session.user) {
session.user.role = token.role
}
return session
},
},
})
// middleware.ts
import { auth } from "@/auth"
import { NextResponse } from "next/server"
export default auth((req) => {
const { pathname } = req.nextUrl
// Protect /admin routes (require admin role)
if (pathname.startsWith("/admin")) {
if (!req.auth || req.auth.user.role !== "admin") {
return NextResponse.redirect(new URL("/unauthorized", req.url))
}
}
return NextResponse.next()
})
完全な例については、references/middleware-patterns.md および templates/advanced/role-based-access.ts を参照してください。
高度な機能
JWT コールバック(カスタムクレーム)
export const { handlers, auth } = NextAuth({
providers: [GitHub],
callbacks: {
async jwt({ token, user, account }) {
// On sign in
if (user) {
token.id = user.id
token.role = user.role
}
// On subsequent requests
return token
},
async session({ session, token }) {
// Expose custom claims to session
session.user.id = token.id
session.user.role = token.role
return session
},
},
})
トークンの更新(OAuth)
トークン更新を伴う Google OAuth:
import Google from "next-auth/providers/google"
export const { handlers, auth } = NextAuth({
providers: [
Google({
authorization: {
params: {
prompt: "consent",
access_type: "offline",
response_type: "code",
},
},
}),
],
callbacks: {
async jwt({ token, account }) {
// First-time login, save tokens
if (account) {
return {
...token,
access_token: account.access_token,
expires_at: account.expires_at,
refresh_token: account.refresh_token,
}
}
// Subsequent logins, check if token expired
if (Date.now() < token.expires_at * 1000) {
return token
}
// Token expired, refresh it
try {
const response = await fetch("https://oauth2.googleapis.com/token", {
method: "POST",
body: new URLSearchParams({
client_id: process.env.AUTH_GOOGLE_ID!,
client_secret: process.env.AUTH_GOOGLE_SECRET!,
grant_type: "refresh_token",
refresh_token: token.refresh_token!,
}),
})
const newTokens = await response.json()
return {
...token,
access_token: newTokens.access_token,
expires_at: Math.floor(Date.now() / 1000 + newTokens.expires_in),
refresh_token: newTokens.refresh_token ?? token.refresh_token,
}
} catch (error) {
console.error("Token refresh error:", error)
token.error = "RefreshTokenError"
return token
}
},
async session({ session, token }) {
session.error = token.error
return session
},
},
})
完全な例については、templates/advanced/jwt-refresh-tokens.ts を参照してください。
重要なルール
✅ 必ず行うこと:
-
本番環境では AUTH_SECRET を設定する
# Generate secret npx auth secret # Add to .env.local AUTH_SECRET=your-generated-secret -
Credentials の authorize() では例外をスローせず、
nullを返すauthorize: async (credentials) => { if (!validUser) { return null // ✅ Correct // throw new Error("Invalid") // ❌ WRONG - causes CallbackRouteError } } -
マジックリンクにはアダプターを使用する
export const { handlers, auth } = NextAuth({ adapter: PrismaAdapter(prisma), // REQUIRED for magic links providers: [Resend], }) -
エッジとの互換性を確保するため、設定を分割する
// auth.config.ts (edge-compatible) export default { providers: [GitHub] } // auth.ts (full config with database) export const { handlers, auth } = NextAuth({ adapter: PrismaAdapter(prisma), session: { strategy: "jwt" }, // Force JWT for edge ...authConfig, }) -
エッジ非対応のアダプターを使用する場合は、JWT セッションを強制する
export const { handlers, auth } = NextAuth({ adapter: PrismaAdapter(prisma), // Not edge-compatible session: { strategy: "jwt" }, // CRITICAL })
❌ 絶対に行わないこと:
-
AUTH_SECRET を設定せずにデプロイする
// WRONG - will fail in production // Missing AUTH_SECRET environment variable -
authorize() でエラーをスローする
authorize: async (credentials) => { throw new Error("Invalid credentials") // ❌ Causes CallbackRouteError } -
非推奨の @next-auth/ アダプターを使用する*
npm install @next-auth/prisma-adapter # ❌ Deprecated npm install @auth/prisma-adapter # ✅ Correct (v5) -
ミドルウェアで、エッジ対応アダプターを使わずにデータベースセッションを使用する
// WRONG - Prisma not edge-compatible export const { handlers, auth } = NextAuth({ adapter: PrismaAdapter(prisma), session: { strategy: "database" }, // ❌ Fails in middleware }) -
v4 と v5 のパッケージを混在させる
npm install [email protected] @auth/[email protected] # ❌ Version mismatch
よくあるエラーと解決方法
1. AUTH_SECRET が設定されていない
エラー:
JWEDecryptionFailed: Invalid secret
原因: AUTH_SECRET 環境変数が設定されていないか、値が正しくありません
解決方法:
# Generate secret
npx auth secret
# Add to .env.local
AUTH_SECRET=your-generated-secret
# In production (Vercel, Cloudflare, etc.)
# Add AUTH_SECRET as environment variable in dashboard
2. CallbackRouteError
エラー:
CallbackRouteError: Illegal arguments: string, undefined
原因: authorize() コールバックでエラーをスローしています
解決方法:
// WRONG
authorize: async (credentials) => {
if (!user) throw new Error("Invalid credentials")
}
// CORRECT
authorize: async (credentials) => {
if (!user) return null
return user
}
3. ルートが見つからない
エラー:
Error: next-auth route not found
原因: API ルートハンドラーのファイルパスが正しくありません
解決方法:
// Ensure file is at EXACT path:
// app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/auth"
export const { GET, POST } = handlers
4. エッジ互換性エラー
エラー:
Module not compatible with edge runtime
原因: データベースセッション戦略でエッジ非対応のアダプターを使用しています
解決方法:
// Option 1: Force JWT sessions
export const { handlers, auth } = NextAuth({
adapter: PrismaAdapter(prisma),
session: { strategy: "jwt" }, // ✅
})
// Option 2: Use edge-compatible adapter (D1)
export const { handlers, auth } = NextAuth({
adapter: D1Adapter(env.DB), // ✅ Edge-compatible
session: { strategy: "database" },
})
5. セッションが更新されない
エラー: セッションの有効期限が切れても更新されません
原因: ミドルウェアがありません
解決方法:
// middleware.ts
export { auth as middleware } from "@/auth"
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}
6~12. その他のエラー
修正方法を含む、文書化された全 12 件のエラーについては、references/common-errors.md を参照してください。
テンプレートのリファレンス
すべてのテンプレートは templates/ ディレクトリにあります。
Next.js テンプレート(5 件)
- auth.ts - シンプルな Next.js 設定(JWT セッション)
- auth.config.ts + auth.ts - 分割設定(エッジ対応)
- multi-provider.ts - OAuth + Credentials + マジックリンク
- middleware.ts - セッションの維持 + ルート保護
- package.json + .env.example - 依存関係 + 環境設定
Cloudflare Workers テンプレート(3 件)
- worker-hono-auth.ts - Hono + Auth.js + D1 の完全な構成
- wrangler.jsonc - D1 バインディング設定
- schema.sql - Auth.js 用 D1 テーブル
プロバイダーテンプレート(3 件)
- oauth-github-google.ts - OAuth の設定
- credentials.ts - Zod による検証を使用したメールアドレス/パスワード認証
- magic-link-resend.ts - パスワードレスのメール認証
高度なテンプレート(2 件)
- jwt-refresh-tokens.ts - Google トークンのローテーション例
- role-based-access.ts - カスタムクレームによる RBAC
これらのファイルをプロジェクトにコピーし、必要に応じてカスタマイズしてください。
パッケージのバージョン
現在(2025-10-26 時点):
{
"next-auth": "4.24.11",
"@auth/core": "0.41.1",
"@auth/d1-adapter": "1.11.1",
"@auth/prisma-adapter": "2.7.5",
"next": "15.3.1",
"hono": "4.7.9"
}
常に最新バージョンを使用してください:
npm install next-auth@latest @auth/core@latest
公式ドキュメント
- Auth.js ドキュメント: https://authjs.dev
- はじめに: https://authjs.dev/getting-started/installation
- プロバイダー: https://authjs.dev/getting-started/providers/oauth
- アダプター: https://authjs.dev/getting-started/adapters
- D1 アダプター: https://authjs.dev/getting-started/adapters/d1
- v5 への移行: https://authjs.dev/getting-started/migrating-to-v5
- エッジ互換性: https://authjs.dev/guides/edge-compatibility
リファレンスドキュメント
詳しくは、以下を参照してください。
- common-errors.md - 文書化されたすべてのエラー 12 件とその解決方法
- edge-compatibility.md - エッジランタイムの互換性マトリックス
- v5-migration-guide.md - v4 → v5 の破壊的変更
- session-strategies.md - JWT とデータベースの比較
- middleware-patterns.md - ルート保護、RBAC
- jwt-customization.md - カスタムクレーム、トークンの更新
- provider-setup-guides.md - OAuth アプリの設定手順
質問や問題がありますか?
- まず
references/common-errors.mdを確認してください - AUTH_SECRET が設定されていることを確認してください
- authorize() でエラーをスローしていないことを確認してください
- 使用しているアダプターのエッジ互換性を確認してください
- 公式ドキュメントを確認してください:https://authjs.dev