Next.js 集成

Better Auth 可以轻松地与 Next.js 集成。在开始之前,请确保你已配置了 Better Auth 实例。如果还没有配置,请查看安装指南。

🌐 Better Auth can be easily integrated with Next.js. Before you start, make sure you have a Better Auth instance configured. If you haven't done that yet, check out the installation.

创建 API 路由

🌐 Create API Route

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

🌐 We need to mount the handler to an API route. Create a route file inside /api/auth/[...all] directory. And add the following code:

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

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

你可以在 better-auth 配置中更改路径,但建议保持为 /api/auth/[...all]

对于 pages 路由,你需要使用 toNodeHandler 而不是 toNextJsHandler,并在 config 对象中将 bodyParser 设置为 false。以下是一个示例:

🌐 For pages route, you need to use toNodeHandler instead of toNextJsHandler and set bodyParser to false in the config object. Here is an example:

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

// Disallow body parsing, we will parse it manually
export const config = { api: { bodyParser: false } }

export default toNodeHandler(auth.handler)

创建客户端

🌐 Create a client

创建一个客户端实例。你可以随意命名文件。在这里,我们在 lib/ 目录下创建 auth-client.ts 文件。

🌐 Create a client instance. You can name the file anything you want. Here we are creating auth-client.ts file inside the lib/ directory.

auth-client.ts
import { createAuthClient } from "better-auth/react" // make sure to import from better-auth/react

export const authClient =  createAuthClient({
    //you can pass client configuration here
})

一旦你创建了客户端,就可以使用它进行注册、登录以及执行其他操作。 其中一些操作是响应式的。客户端使用 nano-store 来存储状态,并在状态变化时重新渲染组件。

🌐 Once you have created the client, you can use it to sign up, sign in, and perform other actions. Some of the actions are reactive. The client uses nano-store to store the state and re-render the components when the state changes.

客户端还使用 better-fetch 来发起请求。你可以将 fetch 配置传递给客户端。

🌐 The client also uses better-fetch to make the requests. You can pass the fetch configuration to the client.

RSC 和服务器操作

🌐 RSC and Server actions

从 auth 实例导出的 api 对象包含了你可以在服务器上执行的所有操作。在 Better Auth 中创建的每个端点都可以作为函数调用,包括插件端点。

🌐 The api object exported from the auth instance contains all the actions that you can perform on the server. Every endpoint made inside Better Auth is a invocable as a function. Including plugins endpoints.

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

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 上获取会话

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>Not authenticated</div>
    }
    return (
        <div>
            <h1>Welcome {session.user.name}</h1>
        </div>
    )
}
由于 RSC 无法设置 cookies,cookie 缓存 在客户端通过服务器操作或路由处理程序与服务器交互之前不会被刷新。

服务器操作 Cookie

🌐 Server Action Cookies

当你在服务器操作中调用需要设置 cookie 的函数时,例如 signInEmailsignUpEmail,cookie 不会被设置。这是因为服务器操作需要使用 Next.js 提供的 cookies 工具来设置 cookie。

🌐 When you call a function that needs to set cookies, like signInEmail or signUpEmail in a server action, cookies won’t be set. This is because server actions need to use the cookies helper from Next.js to set cookies.

为简化这个过程,你可以使用 nextCookies 插件,它会在响应中存在 Set-Cookie 头时自动为你设置 cookie。

🌐 To simplify this, you can use the nextCookies plugin, which will automatically set cookies for you whenever a Set-Cookie header is present in the response.

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

export const auth = betterAuth({
    //...your config
    plugins: [nextCookies()] // make sure this is the last plugin in the array
})

现在,当你调用设置 cookies 的函数时,它们会被自动设置。

🌐 Now, when you call functions that set cookies, they will be automatically set.

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

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

身份验证保护

🌐 Auth Protection

在 Next.js 的代理/中间件中,建议仅检查会话 cookie 是否存在来处理重定向。这样可以避免通过调用 API 或数据库而阻塞请求。

🌐 In Next.js proxy/middleware, it's recommended to only check for the existence of a session cookie to handle redirection. To avoid blocking requests by making API or database calls.

Next.js 16+(代理)

🌐 Next.js 16+ (Proxy)

Next.js 16 用 "proxy" 替代了 "middleware"。你可以使用 Node.js 运行时进行完整的会话验证并进行数据库检查:

🌐 Next.js 16 replaces "middleware" with "proxy". You can use the Node.js runtime for full session validation with database checks:

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

    // THIS IS NOT SECURE!
    // This is the recommended approach to optimistically redirect users
    // We recommend handling auth checks in each page/route
    if(!session) {
        return NextResponse.redirect(new URL("/sign-in", request.url));
    }

    return NextResponse.next();
}

export const config = {
  matcher: ["/dashboard"], // Specify the routes the middleware applies to
};

对于仅使用 Cookie 的检查(更快但安全性较低),请使用 getSessionCookie

🌐 For cookie-only checks (faster but less secure), use getSessionCookie:

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

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

    // THIS IS NOT SECURE!
    // This is the recommended approach to optimistically redirect users
    // We recommend handling auth checks in each page/route
	if (!sessionCookie) {
		return NextResponse.redirect(new URL("/", request.url));
	}

	return NextResponse.next();
}

export const config = {
	matcher: ["/dashboard"], // Specify the routes the middleware applies to
};

**从中间件迁移:**将 middleware.ts 重命名为 proxy.ts,将 middleware 函数重命名为 proxy。所有 Better Auth 方法的使用方式保持不变。

Next.js 15.2.0+(Node.js 运行时中间件)

🌐 Next.js 15.2.0+ (Node.js Runtime Middleware)

从 Next.js 15.2.0 开始,你可以在中间件中使用 Node.js 运行时,通过数据库检查实现完整的会话验证:

🌐 From Next.js 15.2.0, you can use the Node.js runtime in middleware for full session validation with database checks:

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

    // THIS IS NOT SECURE!
    // This is the recommended approach to optimistically redirect users
    // We recommend handling auth checks in each page/route
    if(!session) {
        return NextResponse.redirect(new URL("/sign-in", request.url));
    }

    return NextResponse.next();
}

export const config = {
  runtime: "nodejs", // Required for auth.api calls
  matcher: ["/dashboard"], // Specify the routes the middleware applies to
};

在 Next.js 16 之前的版本中,中间件中的 Node.js 运行时仍处于实验阶段。建议升级到 Next.js 16 或更高版本以获得稳定的代理支持。

Next.js 13-15.1.x(Edge 运行时中间件)

🌐 Next.js 13-15.1.x (Edge Runtime Middleware)

在较旧的 Next.js 版本中,中间件在 Edge Runtime 上运行,无法进行数据库调用。使用基于 cookie 的检查来进行乐观重定向:

🌐 In older Next.js versions, middleware runs on the Edge Runtime and cannot make database calls. Use cookie-based checks for optimistic redirects:

getSessionCookie() 函数不会自动引用 auth.ts 中指定的认证配置。因此,如果你自定义了 cookie 名称或前缀,你需要确保 getSessionCookie() 中的配置与 auth.ts 中定义的配置匹配。

对于 Next.js 版本 15.1.7 及以下

🌐 For Next.js release 15.1.7 and below

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

🌐 If you need the full session object, you'll have to fetch it from the /api/auth/get-session API route. Since Next.js middleware doesn't support running Node.js APIs directly, you must make an HTTP request.

这个示例使用了 better-fetch,但你可以使用任何 fetch 库。

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") || "", // Forward the cookies from the request
		},
	});

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

	return NextResponse.next();
}

export const config = {
	matcher: ["/dashboard"], // Apply middleware to specific routes
};

适用于 Next.js 版本 15.2.0 及以上

🌐 For Next.js release 15.2.0 and above

从 Next.js 15.2.0 开始,你可以在中间件中使用 Node.js 运行时,通过数据库检查实现完整的会话验证:

🌐 From Next.js 15.2.0, you can use the Node.js runtime in middleware for full session validation with database checks:

你可以参考 Next.js 文档以获取有关运行时配置的更多信息,以及如何启用它。
在使用新的运行时时要小心。它是一个实验性功能,可能会发生破坏性更改。

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"], // Apply middleware to specific routes
};

🌐 Cookie-based checks (recommended for all versions)

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

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

    // THIS IS NOT SECURE!
    // This is the recommended approach to optimistically redirect users
    // We recommend handling auth checks in each page/route
	if (!sessionCookie) {
		return NextResponse.redirect(new URL("/", request.url));
	}

	return NextResponse.next();
}

export const config = {
	matcher: ["/dashboard"], // Specify the routes the middleware applies to
};

安全警告: getSessionCookie 函数仅检查会话 cookie 是否存在;它会验证 cookie 的有效性。仅依赖此检查来保障安全是危险的,因为任何人都可以手动创建一个 cookie 来绕过检查。对于任何受保护的操作或页面,你必须始终在服务器端验证会话。

如果你有自定义的 cookie 名称或前缀,可以将其传递给 getSessionCookie 函数。

const sessionCookie = getSessionCookie(request, {
    cookieName: "my_session_cookie",
    cookiePrefix: "my_prefix"
});

或者,你可以使用 getCookieCache 辅助函数从 cookie 缓存中获取会话对象。

🌐 Alternatively, you can use the getCookieCache helper to get the session object from the cookie cache.

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();
}

如何在每个页面/路由中处理身份验证检查

🌐 How to handle auth checks in each page/route

在此示例中,我们在服务器组件中使用 auth.api.getSession 函数获取会话对象,然后检查会话是否有效。如果无效,我们会将用户重定向到登录页面。

🌐 In this example, we are using the auth.api.getSession function within a server component to get the session object, then we are checking if the session is valid. If it's not, we are redirecting the user to the sign-in page.

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>Welcome {session.user.name}</h1>
}

Next.js 16 兼容性

🌐 Next.js 16 Compatibility

Better Auth 完全兼容 Next.js 16。主要的变化是“middleware”现在被称为“proxy”。有关 Next.js 16 及以上版本 proxy 的示例,请参见上面的 Auth Protection 部分。

🌐 Better Auth is fully compatible with Next.js 16. The main change is that "middleware" is now called "proxy". See the Auth Protection section above for Next.js 16+ proxy examples.

迁移指南

🌐 Migration Guide

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

🌐 Use Next.js codemod for automatic migration:

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

或者手动:

🌐 Or manually:

  • middleware.ts 重命名为 proxy.ts
  • 更改函数名:middlewareproxy

所有 Better Auth 方法的工作方式都是相同的。详情请参阅 Next.js 迁移指南

🌐 All Better Auth methods work identically. See the Next.js migration guide for details.