# Nuxt 集成 (/docs/integrations/nuxt)

将 Better Auth 集成到 Nuxt。



在开始之前，请确保你已经配置了 Better Auth 实例。如果还没有，查看 [安装指南](/docs/installation)。

## 挂载处理器 [#挂载处理器]

将 Better Auth 处理器挂载到一个 catch-all Nitro 路由。创建文件 `server/api/auth/[...all].ts`：

```ts title="server/api/auth/[...all].ts"
import { auth } from "~~/lib/auth"; // 导入你的 auth 配置

export default defineEventHandler((event) => {
	return auth.handler(toWebRequest(event));
});
```

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

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

使用 `better-auth/vue` 创建 auth 客户端，这样 `useSession` 会返回 Vue refs：

```ts title="lib/auth-client.ts"
import { createAuthClient } from "better-auth/vue";

export const authClient = createAuthClient();
export const { signIn, signUp, signOut, useSession } = authClient;
```

## 使用会话 [#使用会话]

在页面的 `setup()` 中使用 `authClient.useSession(useFetch)`，即可在服务端加载会话并在客户端补水。传入 Nuxt 的 `useFetch`，这样请求会携带传入的 cookies，并且 payload 会在补水期间复用：

```vue title="app/pages/index.vue"
<script setup lang="ts">
import { authClient } from "~~/lib/auth-client";

const { data: session } = await authClient.useSession(useFetch);
</script>

<template>
	<div v-if="session">
		<p>欢迎，{{ session.user.name }}</p>
		<button @click="authClient.signOut()">退出登录</button>
	</div>
	<button v-else @click="authClient.signIn.social({ provider: 'github' })">
		使用 GitHub 继续
	</button>
</template>
```

对于像弹出层或菜单这类仅在客户端使用的组件，直接调用 `authClient.useSession()`，不要传参数。它会返回一个响应式 ref，并在登录和退出时自动更新。

## 保护页面 [#保护页面]

创建一个具名路由中间件，并通过 `definePageMeta` 将页面关联到该中间件：

```ts title="app/middleware/auth.ts"
import { authClient } from "~~/lib/auth-client";

export default defineNuxtRouteMiddleware(async (to) => {
	const { data: session } = await authClient.useSession(useFetch);
	if (!session.value) {
		return navigateTo({ path: "/login", query: { redirect: to.fullPath } });
	}
});
```

```vue title="app/pages/dashboard.vue"
<script setup lang="ts">
definePageMeta({ middleware: "auth" });
</script>
```

将文件重命名为 `app/middleware/auth.global.ts`，即可使其在每个路由上运行。务必对 `navigateTo(...)` 调用使用 `return`，否则它不会生效。

## 保护服务端路由 [#保护服务端路由]

使用传入的 `event.headers` 调用 `auth.api.getSession`，并用 `createError` 对路由进行保护：

```ts title="server/api/me.get.ts"
import { auth } from "~~/lib/auth";

export default defineEventHandler(async (event) => {
	const session = await auth.api.getSession({ headers: event.headers });
	if (!session?.user) {
		throw createError({ statusCode: 401, statusMessage: "未授权" });
	}
	return { user: session.user };
});
```

如果你需要在很多路由中复用这段逻辑，可以把检查提取到你自己的 `server/utils/` 辅助函数中。

## 在 SSR 期间使用客户端 [#在-ssr-期间使用客户端]

除了 `useSession(useFetch)` 之外，`authClient` 的操作默认不会在 SSR 期间转发 cookies，因此会返回未认证状态。处理方式有两种：

**方案 A：仅在客户端调用。** 使用 `<ClientOnly>` 包裹消费者组件，或者通过 `import.meta.client` 做条件判断：

```vue
<script setup lang="ts">
import { authClient } from "~~/lib/auth-client";

const accounts = ref<Awaited<ReturnType<typeof authClient.listAccounts>>["data"]>();

onMounted(async () => {
	const { data } = await authClient.listAccounts();
	accounts.value = data;
});
</script>
```

**方案 B：创建一个按请求作用域的客户端，在 SSR 期间转发 cookies。** 添加一个 `useAuth` 可组合函数，并与 `useAsyncData` 结合使用：

```ts title="app/composables/useAuth.ts"
import { createAuthClient } from "better-auth/vue";

export function useAuth() {
	const url = useRequestURL();
	const headers = import.meta.server ? useRequestHeaders(["cookie"]) : undefined;
	return createAuthClient({
		baseURL: url.origin,
		fetchOptions: { headers },
	});
}
```

```vue title="app/pages/settings.vue"
<script setup lang="ts">
const { data: accounts } = await useAsyncData("accounts", () =>
	useAuth().listAccounts().then((res) => res.data),
);
</script>
```

## 与 Nuxt 层复用 [#与-nuxt-层复用]

当你想在多个 Nuxt 应用之间复用同一套 auth 配置时（例如一个营销站和一个仪表盘），可以将 `lib/auth.ts`、`server/`、`app/middleware/` 和 `app/composables/` 提取到一个 [Nuxt 层](https://nuxt.com/docs/4.x/getting-started/layers) 中，并在每个应用里继承它：

```ts title="nuxt.config.ts"
export default defineNuxtConfig({
	extends: ["./layers/auth"],
});
```

## 资源与示例 [#资源与示例]

{/* cspell:disable */}

* [`nuxt-modules/better-auth`](https://github.com/nuxt-modules/better-auth)
* [`atinux/nuxthub-better-auth`](https://github.com/atinux/nuxthub-better-auth)
* [`leamsigc/nuxt-better-auth-drizzle`](https://github.com/leamsigc/nuxt-better-auth-drizzle)
* [`nuxtone/nuxt-one`](https://github.com/nuxtone/nuxt-one)

{/* cspell:enable */}

