mcpField
A
auth-js

auth-js

github.com/jackspace安全1647 次安装12 周前更新
代码仓库

关于 auth-js

为 Auth.js v5 提供配置和排错指导的开发技能,面向使用 Next.js 或 Cloudflare Workers 实现身份验证的开发者与编码 Agent。它结合配置示例、会话策略和常见问题说明。

主要功能

  1. 01提供 Next.js 与 Workers 配置步骤
  2. 02说明 JWT 和数据库会话策略
  3. 03涵盖 OAuth、Credentials 与 Magic Link
  4. 04指导适配器及数据库配置
  5. 05列出常见错误和排查要点

适用场景

  1. 01为 Next.js 应用配置登录与会话
  2. 02在 Cloudflare Workers 部署身份验证
  3. 03选择适合运行环境的会话策略
  4. 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 Agent 至关重要:如果你是 Claude Code,正在帮助用户设置 Auth.js:

  1. 在对话开始时明确说明你正在使用此技能
  2. 参考此技能中的模式,而不是依赖一般知识
  3. 避免 references/common-errors.md 中列出的已知问题
  4. 不要猜测——如果不确定,请查阅技能文档

需要用户执行的操作:告诉 Claude 先检查此技能!

请说:“我正在设置 Auth.js——请先检查 auth-js 技能”

为什么这很重要(真实结果)

未激活技能时:

  • ❌ 设置时间:约 15 分钟
  • ❌ 遇到的错误:3-5 个(AUTH_SECRET、CallbackRouteError、边缘环境问题)
  • ❌ 需要手动修复:3-4 次提交
  • ❌ Token 用量:约 15k
  • ❌ 用户信心:需要多次调试

激活技能后:

  • ✅ 设置时间:约 3 分钟
  • ✅ 遇到的错误:0 个
  • ✅ 需要手动修复:0 次
  • ✅ Token 用量:约 6k(减少 60%)
  • ✅ 用户信心:立即成功
此技能可避免的已知问题
  1. 缺少 AUTH_SECRET → JWEDecryptionFailed 错误
  2. CallbackRouteError → 在 authorize() 中抛出异常,而不是返回 null
  3. 找不到路由 → [...nextauth].js 的文件路径不正确
  4. 与边缘环境不兼容 → 在没有边缘兼容适配器的情况下使用数据库会话
  5. PKCE 错误 → OAuth 提供商配置不正确
  6. 会话未更新 → 缺少中间件
  7. v5 迁移问题 → 命名空间更改、JWT salt 更改
  8. D1 绑定错误 → Wrangler 配置不匹配
  9. 数据库与凭据不兼容 → 会话策略不兼容
  10. 生产部署失败 → 缺少环境变量
  11. Token 刷新错误 → 回调实现不正确
  12. 预期为 JSON,却收到 HTML → Next.js 15 中的重写配置问题

技能处于激活状态时,以上问题都会自动得到处理。


目录

  1. 快速开始 - Next.js
  2. 快速开始 - Cloudflare Workers
  3. 核心概念
  4. 会话策略
  5. 提供商设置
  6. 数据库适配器
  7. 中间件模式
  8. 高级功能
  9. 关键规则
  10. 常见错误与修复方法
  11. 模板参考

快速开始: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 支持两种会话策略:

  1. JWT(JSON Web Token) - 未配置适配器时的默认策略

    • ✅ 适用于边缘运行时
    • ✅ 无需查询数据库获取会话
    • ✅ 快速且可扩展
    • ❌ 无法在服务器端使会话失效
    • ❌ 令牌大小有限制
  2. 数据库 - 配置适配器时的默认策略

    • ✅ 完全控制会话(使其失效、延长有效期)
    • ✅ 在数据库中保留审计记录
    • ✅ 令牌大小不受限制
    • ❌ 每次请求都需要查询数据库
    • ❌ 与部分边缘运行时不兼容

决策矩阵:

使用场景推荐策略原因
Next.js App RouterJWT兼容边缘运行时
Cloudflare WorkersJWT 或数据库(搭配 D1)D1 兼容边缘运行时
传统 Node.js数据库完全控制会话
高安全性数据库可以使会话失效
只读会话JWT无数据库开销

详细对比请参阅 references/session-strategies.md。


会话策略

JWT 会话(默认)

适用场景:

  • 部署到边缘运行时(Cloudflare Workers、Vercel Edge)
  • 未配置数据库适配器
  • 只读会话数据
  • 高流量应用(无需查询数据库)

配置:

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

Provider 设置

OAuth Provider(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 Provider(电子邮件/密码)

⚠️ 重要: Credentials Provider 仅支持 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
        }
      },
    }),
  ],
})

⚠️ 重要规则:

  1. 在 authorize() 中绝不要抛出错误——始终返回 null
  2. 原因: 抛出错误会导致 CallbackRouteError,而不是 CredentialsSignin
  3. 检查凭据前,始终使用 Zod 验证
  4. 使用 bcrypt 对密码进行哈希处理,绝不要存储明文密码

完整示例请参阅 templates/providers/credentials.ts。

Magic Link Provider(无密码)

⚠️ 重要: 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。


重要规则

✅ 务必做到:
  1. 在生产环境中设置 AUTH_SECRET

    # Generate secret
    npx auth secret
    
    # Add to .env.local
    AUTH_SECRET=your-generated-secret
    
  2. 在 Credentials 的 authorize() 中返回 null,不要抛出异常

    authorize: async (credentials) => {
      if (!validUser) {
        return null // ✅ Correct
        // throw new Error("Invalid") // ❌ WRONG - causes CallbackRouteError
      }
    }
    
  3. 使用适配器处理 Magic Links

    export const { handlers, auth } = NextAuth({
      adapter: PrismaAdapter(prisma), // REQUIRED for magic links
      providers: [Resend],
    })
    
  4. 拆分配置以兼容边缘运行时

    // 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,
    })
    
  5. 使用非边缘兼容适配器时强制采用 JWT 会话

    export const { handlers, auth } = NextAuth({
      adapter: PrismaAdapter(prisma), // Not edge-compatible
      session: { strategy: "jwt" }, // CRITICAL
    })
    
❌ 切勿这样做:
  1. 未设置 AUTH_SECRET 就部署

    // WRONG - will fail in production
    // Missing AUTH_SECRET environment variable
    
  2. 在 authorize() 中抛出错误

    authorize: async (credentials) => {
      throw new Error("Invalid credentials") // ❌ Causes CallbackRouteError
    }
    
  3. 使用已弃用的 @next-auth/ 适配器*

    npm install @next-auth/prisma-adapter  # ❌ Deprecated
    npm install @auth/prisma-adapter       # ✅ Correct (v5)
    
  4. 在中间件中使用数据库会话,但不使用边缘兼容适配器

    // WRONG - Prisma not edge-compatible
    export const { handlers, auth } = NextAuth({
      adapter: PrismaAdapter(prisma),
      session: { strategy: "database" }, // ❌ Fails in middleware
    })
    
  5. 混用 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 + Magic Links
  • 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

官方文档


参考文档

如需深入了解,请参阅:

  • 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 应用配置说明

有问题?遇到故障?

  1. 先查看 references/common-errors.md
  2. 确认已设置 AUTH_SECRET
  3. 确保没有在 authorize() 中抛出错误
  4. 检查适配器的边缘兼容性
  5. 查看官方文档:https://authjs.dev

评论

支持 Markdown