# 双重身份验证 (2FA) (/docs/plugins/2fa)

通过双重身份验证增强应用的安全性。



`OTP` `TOTP` `备用代码` `受信设备`

双重身份验证 (2FA) 在用户登录时增加了一道额外的安全步骤。用户不仅需要密码，还需提供第二种验证方式。这使得即使密码泄露，未经授权的人也更难访问账户。

此插件提供两种主要的二次验证方法：

1. **OTP (一次性密码)**：发送到用户邮箱或手机的临时代码。
2. **TOTP (基于时间的一次性密码)**：由用户设备上的应用生成的代码。

**附加功能包括：**

* 生成备用代码用于账户恢复

* 启用/禁用 2FA

* 管理受信设备

* 生成备用代码用于账户恢复

* 启用/禁用 2FA

* 管理受信设备

## 安装 [#安装]

<Steps>
  <Step>
    ### 将插件添加到您的认证配置 [#将插件添加到您的认证配置]

    将双重身份验证插件添加到您的认证配置中，并指定您的应用名称作为颁发者。

    ```ts title="auth.ts"
    import { betterAuth } from "better-auth"
    import { twoFactor } from "better-auth/plugins" // [!code highlight]

    export const auth = betterAuth({
        // ... 其他配置选项
        appName: "My App", // 提供您的应用名称。这将用作颁发者。 // [!code highlight]
        plugins: [
            twoFactor() // [!code highlight]
        ]
    })
    ```
  </Step>

  <Step>
    ### 迁移数据库 [#迁移数据库]

    运行迁移或生成模式以向数据库添加必要的字段和表。

    <Tabs items="[&#x22;migrate&#x22;, &#x22;generate&#x22;]">
      <Tab value="migrate">
        <CodeBlockTabs defaultValue="npm" groupId="persist-install">
          <CodeBlockTabsList>
            <CodeBlockTabsTrigger value="npm">
              npm
            </CodeBlockTabsTrigger>

            <CodeBlockTabsTrigger value="pnpm">
              pnpm
            </CodeBlockTabsTrigger>

            <CodeBlockTabsTrigger value="yarn">
              yarn
            </CodeBlockTabsTrigger>

            <CodeBlockTabsTrigger value="bun">
              bun
            </CodeBlockTabsTrigger>
          </CodeBlockTabsList>

          <CodeBlockTab value="npm">
            ```bash
            npx auth migrate
            ```
          </CodeBlockTab>

          <CodeBlockTab value="pnpm">
            ```bash
            pnpm dlx auth migrate
            ```
          </CodeBlockTab>

          <CodeBlockTab value="yarn">
            ```bash
            yarn dlx auth migrate
            ```
          </CodeBlockTab>

          <CodeBlockTab value="bun">
            ```bash
            bun x auth migrate
            ```
          </CodeBlockTab>
        </CodeBlockTabs>
      </Tab>

      <Tab value="generate">
        <CodeBlockTabs defaultValue="npm" groupId="persist-install">
          <CodeBlockTabsList>
            <CodeBlockTabsTrigger value="npm">
              npm
            </CodeBlockTabsTrigger>

            <CodeBlockTabsTrigger value="pnpm">
              pnpm
            </CodeBlockTabsTrigger>

            <CodeBlockTabsTrigger value="yarn">
              yarn
            </CodeBlockTabsTrigger>

            <CodeBlockTabsTrigger value="bun">
              bun
            </CodeBlockTabsTrigger>
          </CodeBlockTabsList>

          <CodeBlockTab value="npm">
            ```bash
            npx auth generate
            ```
          </CodeBlockTab>

          <CodeBlockTab value="pnpm">
            ```bash
            pnpm dlx auth generate
            ```
          </CodeBlockTab>

          <CodeBlockTab value="yarn">
            ```bash
            yarn dlx auth generate
            ```
          </CodeBlockTab>

          <CodeBlockTab value="bun">
            ```bash
            bun x auth generate
            ```
          </CodeBlockTab>
        </CodeBlockTabs>
      </Tab>
    </Tabs>

    参见 [Schema](#schema) 部分以手动添加字段。
  </Step>

  <Step>
    ### 添加客户端插件 [#添加客户端插件]

    添加客户端插件并指定如果用户需要验证第二因素时应重定向到的位置

    ```ts title="auth-client.ts"
    import { createAuthClient } from "better-auth/client"
    import { twoFactorClient } from "better-auth/client/plugins" // [!code highlight]

    export const authClient = createAuthClient({
        plugins: [
            twoFactorClient() // [!code highlight]
        ]
    })
    ```
  </Step>
</Steps>

## 使用 [#使用]

### 启用 2FA [#启用-2fa]

要启用双重身份验证，请调用 `twoFactor.enable`。如果用户拥有邮箱/密码账户，则必须提供密码。您可以在两种方法之间进行选择：

* **`totp`**（默认）——设置认证器应用。用户必须先验证 TOTP 代码，2FA 才会激活。返回 `{ method: "totp", totpURI, backupCodes }`
* **`otp`**——立即启用基于邮箱/短信的代码，无需额外的验证步骤。返回 `{ method: "otp" }`。要求在服务器上配置 `otpOptions.sendOTP`

<Callout type="warn">
  默认情况下，启用 2FA 需要密码。通过 OAuth、passkeys、magic links 或匿名身份验证注册的用户，除非在插件配置中设置 `allowPasswordless: true`，否则无法启用 2FA。此选项不会改变哪些登录方式需要进行 2FA 验证。
</Callout>

**Endpoint:** `POST /two-factor/enable`

### Client Side

```ts
const { data, error } = await authClient.twoFactor.enable({
    password: "secure-password", // required, The user’s password. Required for email/password accounts.
    method: "totp", // The 2FA method to enable.
    issuer: "my-app-name", // Custom issuer for the TOTP URI. Defaults to the app name in your auth config.
});
```

### Server Side

```ts
const data = await auth.api.enableTwoFactor({
    body: {
        password: "secure-password", // required, The user’s password. Required for email/password accounts.
        method: "totp", // The 2FA method to enable.
        issuer: "my-app-name", // Custom issuer for the TOTP URI. Defaults to the app name in your auth config.
    },
    // This endpoint requires session cookies.
    headers: await headers(),
});
```

### Type Definition

```ts
type enableTwoFactor = {
    /**
     * The user’s password. Required for email/password accounts.
     */
    password: string = "secure-password",
    /**
     * The 2FA method to enable.
     */
    method?: "otp" | "totp" = "totp",
    /**
     * Custom issuer for the TOTP URI. Defaults to the app name in your auth config.
     */
    issuer?: string = "my-app-name"
}
```

当 `method` 为 `"totp"`（默认值）时：

* 返回 `{ method: "totp", totpURI, backupCodes }`。使用 `totpURI` 显示二维码
* 默认情况下，在用户验证 TOTP 代码之前，`twoFactorEnabled` 仍为 `false`。当服务器插件配置了 `skipVerificationOnEnable: true` 时，TOTP 会在无需验证注册代码的情况下启用。参见 [验证 TOTP](#totp)

<Callout>
  当用户已经拥有经过验证的 TOTP 认证器时，调用 `twoFactor.enable` 会返回 `TOTP_ALREADY_ENABLED`。开始新的注册前，请先禁用当前认证器。
</Callout>

当 `method` 为 `"otp"` 时：

* 返回 `{ method: "otp" }`。`twoFactorEnabled` 会立即设置为 `true`
* 要求在服务器上配置 `otpOptions.sendOTP`
* 登录时会通过已配置的 `sendOTP` 函数发送 OTP 代码。通过数据库 hook 直接设置 `twoFactorEnabled` 可实现相同的效果

### 使用 2FA 登录 [#使用-2fa-登录]

当启用了 2FA 的用户尝试通过邮箱、用户名或手机号登录时，响应对象将包含设置为 `true` 的 `twoFactorRedirect`，以及 `twoFactorMethods`——一个包含该用户可用 2FA 方法的数组（例如 `["totp"]`、`["totp", "otp"]`）。使用 `twoFactorMethods` 来决定显示哪种验证界面。

默认情况下，2FA 登录强制适用于基于凭证的登录端点：`/sign-in/email`、`/sign-in/username` 和 `/sign-in/phone-number`。诸如邮箱 OTP、magic link、OAuth/社交登录、passkey、匿名登录以及类似的无密码流程，默认不会被 2FA 限制。

如果您的应用需要对这些登录方式也强制要求 2FA，请为这些端点添加自定义 hook 处理，并在将登录视为完成之前，把用户重定向到您的 2FA 验证流程中。

<Callout type="warn">
  当启用了 2FA 的用户通过凭证端点登录时，插件会发起 2FA 挑战，而不是完成登录。作为此过程的一部分，待处理会话会被丢弃，`ctx.context.newSession` 会被重置为 `null`——在用户验证第二因素之前，不会有已认证会话。读取 `ctx.context.newSession` 的服务器端 hooks（例如登录端点上的 `after` hooks）在访问 `newSession.user` 之前必须先检查是否为 `null`，否则在 2FA 挑战进行时它们会抛出错误。
</Callout>

您可以在 `onSuccess` 回调中处理此情况，或在插件配置中提供 `onTwoFactorRedirect` 回调。

```tsx
import { authClient } from "@/lib/auth-client"

await authClient.signIn.email({
        email: "user@example.com",
        password: "password123",
    },
    {
        async onSuccess(context) {
            if (context.data.twoFactorRedirect) {
                const methods = context.data.twoFactorMethods // 例如 ["totp", "otp"]
                // 根据可用的方法显示适当的 2FA 验证 UI
            }
        },
    }
)
```

使用 `onTwoFactorRedirect` 配置示例：

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

const authClient = createAuthClient({
    plugins: [
        twoFactorClient({
            onTwoFactorRedirect({ twoFactorMethods }){
                // twoFactorMethods 例如 ["totp", "otp"]
                // 在全局处理 2FA 验证
            },
        }),
    ],
});
```

使用 `twoFactorPage` 配置：

```ts title="sign-in.ts"
import { createAuthClient } from "better-auth/client";
import { twoFactorClient } from "better-auth/client/plugins";

const authClient = createAuthClient({
    plugins: [
        twoFactorClient({
            twoFactorPage: "/two-factor", // 如果用户需要验证第二因素，重定向到该页面
        }),
    ],
});
```

<Callout type="warn">
  使用 `twoFactorPage` 选项会导致在将用户重定向到双重身份验证页面时发生完整页面重载。如果要避免页面重载，请考虑改用 `onTwoFactorRedirect` 回调以在应用程序内以编程方式处理重定向。
</Callout>

<Callout type="warn">
  **使用 `auth.api`**

  当您在服务器上调用 `auth.api.signInEmail`，并且用户启用了 2FA 时，它将返回一个对象，其中 `twoFactorRedirect` 设置为 `true`。此行为在 TypeScript 中无法推断，可能会产生误导。您可以使用 `in` 来检查 `twoFactorRedirect` 是否设置为 `true`。

  `authClient.twoFactor.*` 在浏览器中自动处理 cookie。如果您在服务器上继续使用 `auth.api.*` 进行 2FA 流程，则必须传递相关的标头，以便 Better Auth 可以读取当前的 2FA 状态并设置相应的 2FA/session cookie。下方生成的示例使用 `await headers()` 获取这些标头，但在其他框架中，您应该传递等效的传入请求头。

  如果在同一个服务器流程中链式调用多个 `auth.api.*` 调用，请确保将前一个身份验证响应中的 cookie 传递到下一个调用中。

  ```ts title="sign-in.ts"
  import { auth } from "@/lib/auth"

  const { headers: responseHeaders, response } = await auth.api.signInEmail({
  	returnHeaders: true,
  	body: {
  		email: "test@test.com",
  		password: "test",
  	},
  });

  if ("twoFactorRedirect" in response) {
  	// response.twoFactorMethods 例如 ["totp", "otp"]
  	// 将 responseHeaders 中的 cookie 传递到下一个 auth.api 2FA 调用。
  	// 在适当的位置处理 2FA 验证
  }
  ```
</Callout>

### 禁用 2FA [#禁用-2fa]

要禁用双重身份验证，请使用用户的密码（凭证账户必填）调用 `twoFactor.disable`。如果启用了 `allowPasswordless`，对于没有凭证账户的用户可以省略密码。

**Endpoint:** `POST /two-factor/disable`

### Client Side

```ts
const { data, error } = await authClient.twoFactor.disable({
    password, // 用户的密码（凭证账户必填）
});
```

### Server Side

```ts
const data = await auth.api.disableTwoFactor({
    body: {
        password, // 用户的密码（凭证账户必填）
    },
    // This endpoint requires session cookies.
    headers: await headers(),
});
```

### Type Definition

```ts
type disableTwoFactor = {
    /**
     * 用户的密码（凭证账户必填）
     */
    password?: string
}
```

### TOTP [#totp]

TOTP（基于时间的一次性密码）是一种使用时间计数器为每次登录生成唯一密码的算法。每隔固定时间（Better Auth 默认为 30 秒）生成一个新密码。它解决了传统密码可能被遗忘、窃取或猜测的问题。虽然 OTP 也解决了一部分问题，但通过短信或邮箱发送 OTP 的可靠性较差（甚至更有风险，因为它可能带来新的攻击面）。

而 TOTP 是离线生成代码，既安全又便捷。只需在手机上安装认证器应用即可。

#### 获取 TOTP URI [#获取-totp-uri]

启用 2FA 后，可以获取 TOTP URI 并向用户展示。该 URI 是服务器基于 `secret` 和 `issuer` 生成的，用于生成二维码，供用户用认证器扫描。

**Endpoint:** `POST /two-factor/get-totp-uri`

### Client Side

```ts
const { data, error } = await authClient.twoFactor.getTotpUri({
    password, // 用户的密码（凭证账户必填）
});
```

### Server Side

```ts
const data = await auth.api.getTOTPURI({
    body: {
        password, // 用户的密码（凭证账户必填）
    },
    // This endpoint requires session cookies.
    headers: await headers(),
});
```

### Type Definition

```ts
type getTOTPURI = {
    /**
     * 用户的密码（凭证账户必填）
     */
    password?: string
}
```

<Callout type="warn">
  请将 TOTP URI 视为机密信息。它包含用户的邮箱以及用于生成 TOTP 代码的共享密钥。请在浏览器中本地生成二维码，而不要将 URI 发送到第三方二维码服务。
</Callout>

**示例：使用 React**

获取到 TOTP URI 后，可以将其用于生成二维码，供用户使用认证器应用扫描。

```tsx
import { authClient } from "@/lib/auth-client"
import QRCode from "react-qr-code";

export default function UserCard({ password }: { password: string }){
    const { data: session } = authClient.useSession();
	const { data: qr } = useQuery({
		queryKey: ["two-factor-qr"],
		queryFn: async () => {
			const res = await authClient.twoFactor.getTotpUri({ password });
			return res.data;
		},
		enabled: !!session?.user.twoFactorEnabled,
	});
    return (
        <QRCode value={qr?.totpURI || ""} />
   )
}
```

#### 验证 TOTP [#验证-totp]

用户输入 2FA 代码后，可以调用 `twoFactor.verifyTotp` 方法进行验证。`Better Auth` 遵循标准做法，接受当前时间段前后各一个周期内的代码，确保用户即使存在轻微时间偏差也可成功认证。

**Endpoint:** `POST /two-factor/verify-totp`

### Client Side

```ts
const { data, error } = await authClient.twoFactor.verifyTotp({
    code: "012345", // required, 要验证的 OTP 代码。
    trustDevice: true, // 如果为 true，设备将被信任 30 天。在此时间内的每次登录请求中都会刷新。
});
```

### Server Side

```ts
const data = await auth.api.verifyTOTP({
    body: {
        code: "012345", // required, 要验证的 OTP 代码。
        trustDevice: true, // 如果为 true，设备将被信任 30 天。在此时间内的每次登录请求中都会刷新。
    },
    // 传递当前请求标头，以便 Better Auth 可以读取并设置 2FA/session cookie。
    headers: await headers(),
});
```

### Type Definition

```ts
type verifyTOTP = {
    /**
     * 要验证的 OTP 代码。
     */
    code: string = "012345"
    /**
     * 如果为 true，设备将被信任 30 天。在此时间内的每次登录请求中都会刷新。
     */
    trustDevice?: boolean = true
}
```

### OTP [#otp]

OTP（一次性密码）与 TOTP 类似，但生成的随机码会通过邮件或短信发送给用户。

在使用 OTP 进行二次验证之前，您需要在 Better Auth 实例中配置 `sendOTP`。该函数负责将 OTP 发送给用户的邮箱、手机或其他支持的方式。

```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { twoFactor } from "better-auth/plugins"

export const auth = betterAuth({
    plugins: [
        twoFactor({
          	otpOptions: {
				async sendOTP({ user, otp }, ctx) {
                    // 向用户发送 otp
				},
			},
        })
    ]
})
```

#### 发送 OTP [#发送-otp]

发送 OTP 通过调用客户端的 `authClient.twoFactor.sendOtp` 函数或服务器端的 `auth.api.sendTwoFactorOTP` 完成。该函数会触发您在 Better Auth 配置中提供的 `sendOTP` 实现。

**Endpoint:** `POST /two-factor/send-otp`

### Client Side

```ts
const { data, error } = await authClient.twoFactor.sendOtp({
    trustDevice: true, // 如果为 true，设备将被信任 30 天。在此时间内的每次登录请求中都会刷新。
});
if (data) {
    // 重定向或显示用户输入代码的界面
}
```

### Server Side

```ts
const data = await auth.api.sendTwoFactorOTP({
    body: {
        trustDevice: true, // 如果为 true，设备将被信任 30 天。在此时间内的每次登录请求中都会刷新。
    },
    // 传递当前请求标头，以便 Better Auth 可以读取并设置 2FA/session cookie。
    headers: await headers(),
});
if (data) {
    // 重定向或显示用户输入代码的界面
}
```

### Type Definition

```ts
type sendTwoFactorOTP = {
    /**
     * 如果为 true，设备将被信任 30 天。在此时间内的每次登录请求中都会刷新。
     */
    trustDevice?: boolean = true
}
```

#### 验证 OTP [#验证-otp]

用户输入 OTP 代码后，您可以使用客户端的 `authClient.twoFactor.verifyOtp` 或服务器端的 `auth.api.verifyTwoFactorOTP` 进行验证。

**Endpoint:** `POST /two-factor/verify-otp`

### Client Side

```ts
const { data, error } = await authClient.twoFactor.verifyOtp({
    code: "012345", // required, 要验证的 OTP 代码。
    trustDevice: true, // 如果为 true，设备将被信任 30 天。在此时间内的每次登录请求中都会刷新。
});
```

### Server Side

```ts
const data = await auth.api.verifyTwoFactorOTP({
    body: {
        code: "012345", // required, 要验证的 OTP 代码。
        trustDevice: true, // 如果为 true，设备将被信任 30 天。在此时间内的每次登录请求中都会刷新。
    },
    // 传递当前请求标头，以便 Better Auth 可以读取并设置 2FA/session cookie。
    headers: await headers(),
});
```

### Type Definition

```ts
type verifyTwoFactorOTP = {
    /**
     * 要验证的 OTP 代码。
     */
    code: string = "012345"
    /**
     * 如果为 true，设备将被信任 30 天。在此时间内的每次登录请求中都会刷新。
     */
    trustDevice?: boolean = true
}
```

### 备用代码 [#备用代码]

备用代码存储于数据库。当用户失去手机或邮箱访问权限时，可用于账户恢复。

#### 生成备用代码 [#生成备用代码]

为账户恢复生成备用代码：

**Endpoint:** `POST /two-factor/generate-backup-codes`

### Client Side

```ts
const { data, error } = await authClient.twoFactor.generateBackupCodes({
    password, // 用户的密码（凭证账户必填）。
});
if (data) {
    // 向用户展示备用代码
}
```

### Server Side

```ts
const data = await auth.api.generateBackupCodes({
    body: {
        password, // 用户的密码（凭证账户必填）。
    },
    // This endpoint requires session cookies.
    headers: await headers(),
});
if (data) {
    // 向用户展示备用代码
}
```

### Type Definition

```ts
type generateBackupCodes = {
    /**
     * 用户的密码（凭证账户必填）。
     */
    password?: string
}
```

<Callout type="warn">
  生成备用代码时，旧备用代码将被删除并生成新的。
</Callout>

#### 使用备用代码 [#使用备用代码]

您可以允许用户使用备用代码作为账户恢复方式。

**Endpoint:** `POST /two-factor/verify-backup-code`

### Client Side

```ts
const { data, error } = await authClient.twoFactor.verifyBackupCode({
    code: "123456", // required, 要验证的备用代码。
    disableSession: false, // 如果为 true，不会设置会话 cookie。
    trustDevice: true, // 如果为 true，设备将被信任 30 天。在此时间内的每次登录请求中都会刷新。
});
```

### Server Side

```ts
const data = await auth.api.verifyBackupCode({
    body: {
        code: "123456", // required, 要验证的备用代码。
        disableSession: false, // 如果为 true，不会设置会话 cookie。
        trustDevice: true, // 如果为 true，设备将被信任 30 天。在此时间内的每次登录请求中都会刷新。
    },
    // 传递当前请求标头，以便 Better Auth 可以读取并设置 2FA/session cookie。
    headers: await headers(),
});
```

### Type Definition

```ts
type verifyBackupCode = {
    /**
     * 要验证的备用代码。
     */
    code: string = "123456"
    /**
     * 如果为 true，不会设置会话 cookie。
     */
    disableSession?: boolean = false
    /**
     * 如果为 true，设备将被信任 30 天。在此时间内的每次登录请求中都会刷新。
     */
    trustDevice?: boolean = true
}
```

<Callout>
  一旦备用代码被使用，它将从数据库中移除且无法再次使用。
</Callout>

#### 查看备用代码 [#查看备用代码]

要向用户展示备用代码，可以在服务器调用 `viewBackupCodes`，返回备用代码。请确保仅允许拥有刚创建的新鲜会话的用户执行此操作。

**Endpoint:** `POST /two-factor/view-backup-codes`

### Server Side

```ts
const data = await auth.api.viewBackupCodes({
    body: {
        userId: "user-id", // 要查看所有备用代码的用户 ID。
    },
});
```

### Type Definition

```ts
type viewBackupCodes = {
    /**
     * 要查看所有备用代码的用户 ID。
     */
    userId?: string | null = "user-id"
}
```

### 受信设备 [#受信设备]

您可以通过向 `verifyTotp` 或 `verifyOtp` 传入 `trustDevice` 来标记设备为受信设备。

```ts
const verify2FA = async (code: string) => {
    const { data, error } = await authClient.twoFactor.verifyTotp({
        code,
        trustDevice: true, // 将当前设备标记为受信设备 // [!code highlight]
    })
    if (data) {
        // 2FA 验证成功且设备被标记为受信
    }
}
```

当 `trustDevice` 设置为 `true`，当前设备将在 30 天内被记为受信设备。在此期间，用户通过该设备再次登录时不会被提示进行 2FA 验证。每次成功登录都会刷新该受信期限。

### 发布者（Issuer） [#发布者issuer]

通过添加 `issuer`，您可以设置应用名称，该名称会显示在 2FA 应用中。

例如，若用户使用 Google Auth，默认 appName 会显示为 `Better Auth`。您可如下配置，使其显示为 `my-app-name`。

```ts
twoFactor({
    issuer: "my-app-name" // [!code highlight]
})
```

***

## 模式 (Schema) [#模式-schema]

该插件需要在 `user` 表中添加 1 个额外字段，且新增 1 个表用于存储双重身份验证数据。

表：`user`。



<DatabaseTable name="user" fields="twoFactorUserTableFields" />

表：`twoFactor`



<DatabaseTable name="twoFactor" fields="twoFactorTableFields" />

## 配置选项 [#配置选项]

### 服务器端 [#服务器端]

**twoFactorTable**：存储双重身份验证数据的表名。默认值：`twoFactor`。

**issuer**：自定义 TOTP URI 的签发者名称。默认值为 `appName`。

**skipVerificationOnEnable**：无需验证注册代码即可立即激活 TOTP。默认值为 `false`。

**allowPasswordless**：允许对没有凭据账户的用户在没有密码的情况下启用和管理 2FA。如果存在凭据账户，则仍然需要密码。此选项不会更改哪些登录方式会在 2FA 时被质询。

**签发者**：签发者是您的应用程序名称。它用于生成 TOTP 代码，并会显示在身份验证器应用中。

**TOTP 选项**

TOTP 的相关配置。



<TypeTable type="twoFactorTotpOptionsType" />

**OTP 选项**

与 OTP 相关的配置。



<TypeTable type="twoFactorOtpOptionsType" />

**备用代码选项**

当用户启用双因素认证时，备用代码会在数据库中生成并存储。如果用户无法访问其手机或电子邮件，这些代码可用于恢复对账户的访问。



<TypeTable type="twoFactorBackupCodeOptionsType" />

**账户锁定**

在登录期间多次验证失败后，账户会被临时锁定。该限制按账户生效，适用于所有登录挑战和所有因素：TOTP、OTP 和备用代码共用一个计数器，验证成功会重置该计数器。被锁定的尝试会返回带有 `ACCOUNT_TEMPORARILY_LOCKED` 错误码的 `429`。默认启用。



<TypeTable type="twoFactorAccountLockoutOptionsType" />

### 客户端 [#客户端]

当用户启用双重身份验证时，备用代码会被生成并存储，用于在用户无法访问手机或邮箱时恢复账户。

<TypeTable
  type="{
amount: {
    description: &#x22;生成的备用代码数量&#x22;,
    type: &#x22;number&#x22;,
    default: 10,
},
length: {
    description: &#x22;备用代码长度&#x22;,
    type: &#x22;number&#x22;,
    default: 10,
},
customBackupCodesGenerate: {
    description: &#x22;自定义生成备用代码的函数，无参数，返回字符串数组。&#x22;,
    type: &#x22;function&#x22;,
},
storeBackupCodes: {
    description: &#x22;备用代码在数据库中的存储方式，明文或加密，也可自定义加密器。&#x22;,
    type: &#x22;string&#x22;,
    default: &#x22;plain&#x22;,
},
}"
/>

### 客户端 [#客户端-1]

在客户端使用双重身份验证插件时，需要将其添加到插件列表中。

```ts title="auth-client.ts"
import { createAuthClient } from "better-auth/client"
import { twoFactorClient } from "better-auth/client/plugins"

const authClient =  createAuthClient({
    plugins: [
        twoFactorClient({ // [!code highlight]
            onTwoFactorRedirect({ twoFactorMethods }){ // [!code highlight]
                // twoFactorMethods 例如 ["totp", "otp"] // [!code highlight]
                window.location.href = "/2fa" // 处理 2FA 验证重定向 // [!code highlight]
            } // [!code highlight]
        }) // [!code highlight]
    ]
})
```

**选项**

`onTwoFactorRedirect`：当用户需要验证其双重身份验证代码时调用的回调函数。接收一个包含 `twoFactorMethods` 的上下文对象——一个已启用的双重身份验证方法数组（例如 `["totp", "otp"]`）。这可用于将用户重定向到适当的 2FA 页面。

