# Next.js 集成 (/docs/integrations/next)

将 Better Auth 集成到 Next.js 中。



Better Auth 可以轻松集成到 Next.js 中。在开始之前，确保你已经配置好了 Better Auth 实例。如果还没有，可以查看[安装指南](/docs/installation)。

### 创建 API 路由 [#创建-api-路由]

我们需要将处理程序挂载到 API 路由中。在 `/api/auth/[...all]` 目录中创建一个路由文件，并添加以下代码：

```ts title="api/auth/[...all]/route.ts"
import { auth } from "@/lib/auth";
import { toNextJsHandler } from "better-auth/next-js";

export const { GET, POST } = toNextJsHandler(auth);
```

<Callout type="info">
  你可以在 Better Auth 配置中更改路径，但建议保持为 `/api/auth/[...all]`
</Callout>

对于 `pages` 路由，你需要使用 `toNodeHandler` 而不是 `toNextJsHandler`，并且在 `config` 对象中将 `bodyParser` 设置为 `false`。示例如下：

```ts title="pages/api/auth/[...all].ts"
import { toNodeHandler } from "better-auth/node"
import { auth } from "@/lib/auth"

// 禁用 body 解析，我们将手动解析
export const config = { api: { bodyParser: false } }

export default toNodeHandler(auth.handler)
```

## 创建客户端 [#创建客户端]

创建一个客户端实例。文件名可以自定义，这里我们在 `lib/` 目录下创建 `auth-client.ts` 文件。

```ts title="auth-client.ts"
import { createAuthClient } from "better-auth/react" // 确保从 better-auth/react 导入

export const authClient =  createAuthClient({
    // 你可以在这里传入客户端配置
})
```

创建客户端后，你可以用它完成注册、登录及其他操作。\
部分操作是响应式的。客户端使用 [nano-store](https://github.com/nanostores/nanostores) 来存储状态，并在状态变化时重新渲染组件。

客户端还使用 [better-fetch](https://github.com/bekacru/better-fetch) 来发起请求，你可以将 fetch 配置传递给客户端。

## RSC 和服务器操作 [#rsc-和服务器操作]

从认证实例导出的 `api` 对象包含你在服务器端可以执行的所有操作。Better Auth 内部创建的每个端点都可以像函数一样被调用，包括插件端点。

**示例：在服务器操作中获取会话**

```tsx title="server.ts"
import { auth } from "@/lib/auth"
import { headers } from "next/headers"

const someAuthenticatedAction = async () => {
    "use server";
    const session = await auth.api.getSession({
        headers: await headers()
    })
};
```

**示例：在 RSC 中获取会话**

```tsx
import { auth } from "@/lib/auth"
import { headers } from "next/headers"

export async function ServerComponent() {
    const session = await auth.api.getSession({
        headers: await headers()
    })
    if(!session) {
        return <div>未认证</div>
    }
    return (
        <div>
            <h1>欢迎 {session.user.name}</h1>
        </div>
    )
}
```

<Callout type="warn">
  由于 RSC 无法设置 Cookie，

  [Cookie 缓存](/docs/concepts/session-management#cookie-缓存)

   不会被刷新，除非通过服务器 Actions 或路由处理器从客户端与服务器交互。
</Callout>

### 服务器操作中的 Cookie [#服务器操作中的-cookie]

当你在服务器操作中调用需要设置 Cookie 的函数，如 `signInEmail` 或 `signUpEmail`，Cookie 不会被自动设置。因为服务器操作需要使用 Next.js 的 `cookies` 助手来设置 Cookie。

为简化操作，你可以使用 `nextCookies` 插件，它会在响应头中包含 `Set-Cookie` 时自动设置 Cookie。

```ts title="auth.ts"
import { betterAuth } from "better-auth";
import { nextCookies } from "better-auth/next-js";

export const auth = betterAuth({
    // ...你的配置
    plugins: [nextCookies()] // 确保这是数组中的最后一个插件 // [!code highlight]
})
```

现在，当你调用设置 Cookie 的函数时，Cookie 会被自动设置。

```ts
"use server";
import { auth } from "@/lib/auth"

const signIn = async () => {
    await auth.api.signInEmail({
        body: {
            email: "user@email.com",
            password: "password",
        }
    })
}
```

## 认证保护 [#认证保护]

在 Next.js 的代理（proxy）/中间件中，建议仅检查会话 Cookie 是否存在来处理重定向，以避免通过 API 或数据库调用阻塞请求。

### Next.js 16+（代理） [#nextjs-16代理]

Next.js 16 使用“代理”替代“中间件”。你可以使用 Node.js 运行时来进行完整的带数据库验证的会话校验：

```ts title="proxy.ts"
import { NextRequest, NextResponse } from "next/server";
import { headers } from "next/headers";
import { auth } from "@/lib/auth";

export async function proxy(request: NextRequest) {
    const session = await auth.api.getSession({
        headers: await headers()
    })

    if(!session) {
        return NextResponse.redirect(new URL("/sign-in", request.url));
    }

    return NextResponse.next();
}

export const config = {
  matcher: ["/dashboard"], // 指定中间件适用的路由
};
```

可使用仅基于 Cookie 的校验（速度更快但安全性较低），调用 `getSessionCookie`：

```ts title="proxy.ts"
import { NextRequest, NextResponse } from "next/server";
import { getSessionCookie } from "better-auth/cookies";

export async function proxy(request: NextRequest) {
	const sessionCookie = getSessionCookie(request);

    // 这并不安全！
    // 这是推荐用于乐观重定向用户的做法
    // 建议在每个页面/路由中处理认证校验
	if (!sessionCookie) {
		return NextResponse.redirect(new URL("/", request.url));
	}

	return NextResponse.next();
}

export const config = {
	matcher: ["/dashboard"], // 指定中间件适用的路由
};
```

<Callout type="info">
  **从中间件迁移：** 将 `middleware.ts` 重命名为 `proxy.ts`，并将 `middleware` 函数重命名为 `proxy`。所有 Better Auth 方法保持不变。
</Callout>

### Next.js 15.2.0+（Node.js 运行时中间件） [#nextjs-1520nodejs-运行时中间件]

从 Next.js 15.2.0 开始，你可以在中间件中使用 Node.js 运行时来进行完整的带数据库验证的会话校验：

```ts title="middleware.ts"
import { NextRequest, NextResponse } from "next/server";
import { headers } from "next/headers";
import { auth } from "@/lib/auth";

export async function middleware(request: NextRequest) {
    const session = await auth.api.getSession({
        headers: await headers()
    })
    
    if(!session) {
        return NextResponse.redirect(new URL("/sign-in", request.url));
    }

    return NextResponse.next();
}

export const config = {
  runtime: "nodejs", // 调用 auth.api 需要此配置
  matcher: ["/dashboard"], // 指定中间件适用的路由
};
```

<Callout type="warn">
  Node.js 运行时在 Next.js 16 之前的中间件中是实验性的。建议升级到 Next.js 16+ 以获得稳定的代理支持。
</Callout>

### Next.js 13-15.1.x（Edge 运行时中间件） [#nextjs-13-151xedge-运行时中间件]

旧版本 Next.js 的中间件运行在 Edge 运行时，无法执行数据库调用。使用基于 Cookie 的校验实现乐观重定向：

<Callout type="warn">
  `getSessionCookie()` 函数不会自动引用 `auth.ts` 中指定的 auth 配置。因此，如果你自定义了 Cookie 名称或前缀，你需要确保 `getSessionCookie()` 中的配置与 `auth.ts` 中定义的配置相匹配。
</Callout>

#### Next.js 版本 `15.1.7` 及以下 [#nextjs-版本-1517-及以下]

如果你需要完整的会话对象，必须从 `/api/auth/get-session` API 路由获取。由于 Next.js 中间件不能直接执行 Node.js API，你必须发起 HTTP 请求。

<Callout>
  示例使用 [better-fetch](https://better-fetch.vercel.app)，你也可以使用任何其他 fetch 库。
</Callout>

```ts title="middleware.ts"
import { betterFetch } from "@better-fetch/fetch";
import type { auth } from "@/lib/auth";
import { NextRequest, NextResponse } from "next/server";

type Session = typeof auth.$Infer.Session;

export async function middleware(request: NextRequest) {
	const { data: session } = await betterFetch<Session>("/api/auth/get-session", {
		baseURL: request.nextUrl.origin,
		headers: {
			cookie: request.headers.get("cookie") || "", // 转发请求中的 Cookie
		},
	});

	if (!session) {
		return NextResponse.redirect(new URL("/sign-in", request.url));
	}

	return NextResponse.next();
}

export const config = {
	matcher: ["/dashboard"], // 仅对特定路由应用中间件
};
```

#### Next.js 版本 `15.2.0` 及以后 [#nextjs-版本-1520-及以后]

从 Next.js 15.2.0 起，你可以在中间件中使用 Node.js 运行时，进行完整的带数据库验证的会话校验：

<Callout type="warn">
  请参考 [Next.js 文档](https://nextjs.org/docs/app/building-your-application/routing/middleware#runtime) 了解运行时配置及开启方法。\
  注意该新运行时为实验特性，可能存在破坏性变更。
</Callout>

```ts title="middleware.ts"
import { NextRequest, NextResponse } from "next/server";
import { headers } from "next/headers";
import { auth } from "@/lib/auth";

export async function middleware(request: NextRequest) {
    const session = await auth.api.getSession({
        headers: await headers()
    })

    if(!session) {
        return NextResponse.redirect(new URL("/sign-in", request.url));
    }

    return NextResponse.next();
}

export const config = {
  runtime: "nodejs",
  matcher: ["/dashboard"], // 仅对特定路由应用中间件
};
```

#### 基于 Cookie 的校验（推荐适用于所有版本） [#基于-cookie-的校验推荐适用于所有版本]

```ts title="middleware.ts"
import { NextRequest, NextResponse } from "next/server";
import { getSessionCookie } from "better-auth/cookies";

export async function middleware(request: NextRequest) {
	const sessionCookie = getSessionCookie(request);

    // 这并不安全！
    // 这是推荐用于乐观重定向用户的做法
    // 建议在每个页面/路由中处理认证校验
	if (!sessionCookie) {
		return NextResponse.redirect(new URL("/", request.url));
	}

	return NextResponse.next();
}

export const config = {
	matcher: ["/dashboard"], // 指定中间件适用的路由
};
```

<Callout type="warn">
  **安全警告：** `getSessionCookie` 函数仅检查会话 Cookie 是否存在；它**不**会验证 Cookie。**仅依赖此检查存在安全风险**，任何人都可以手动创建 Cookie 来绕过它。你必须始终在服务器端验证会话，以保护任何受保护的资源或操作。
</Callout>

<Callout type="info">
  如果你使用了自定义的 Cookie 名称或前缀，你可以将它们传递给 `getSessionCookie` 函数。

  ```ts
  const sessionCookie = getSessionCookie(request, {
      cookieName: "my_session_cookie",
      cookiePrefix: "my_prefix"
  });
  ```
</Callout>

你也可以使用 `getCookieCache` 助手从 Cookie 缓存中获取会话对象。

```ts title="middleware.ts"
import { getCookieCache } from "better-auth/cookies";

export async function middleware(request: NextRequest) {
	const session = await getCookieCache(request);
	if (!session) {
		return NextResponse.redirect(new URL("/sign-in", request.url));
	}
	return NextResponse.next();
}
```

### 如何在每个页面/路由中处理认证校验 [#如何在每个页面路由中处理认证校验]

此示例中，我们在服务器组件中使用 `auth.api.getSession` 获取会话对象，然后验证其有效性。如果无效，跳转至登录页面。

```tsx title="app/dashboard/page.tsx"
import { auth } from "@/lib/auth";
import { headers } from "next/headers";
import { redirect } from "next/navigation";

export default async function DashboardPage() {
    const session = await auth.api.getSession({
        headers: await headers()
    })

    if(!session) {
        redirect("/sign-in")
    }

    return <h1>欢迎 {session.user.name}</h1>
}
```

## Next.js 16 兼容性 [#nextjs-16-兼容性]

Better Auth 与 Next.js 16 完全兼容。主要变化是“中间件”改为“代理”。详见上文[认证保护](#auth-protection)章节中的 Next.js 16+ 代理示例。

### 迁移指南 [#迁移指南]

使用 Next.js codemod 进行自动迁移：

```bash
npx @next/codemod@canary middleware-to-proxy .
```

或者手动操作：

* 将 `middleware.ts` 重命名为 `proxy.ts`
* 将函数名从 `middleware` 改为 `proxy`

所有 Better Auth 方法保持不变。详细内容请参考 [Next.js 迁移指南](https://nextjs.org/docs/app/api-reference/file-conventions/proxy#migration-to-proxy)。

