twoFactor Skill:在 Better Auth 中落地 TOTP/OTP 雙因素認證

前言

生產環境裏,郵箱加密碼的單因素登錄很難滿足安全與合規要求。自己從零實現 2FA,通常要處理 TOTP 算法、OTP 下發、備用碼、登錄中間態 Cookie、可信設備與限流等多塊邏輯,容易漏細節或寫出脆弱流程。Better Auth 已通過 twoFactor 插件把這些能力收進一套配置;twoFactor Agent Skill 則把官方實踐整理成可被編碼助手直接引用的說明,減少 AI 生成不完整或錯誤的 2FA 代碼。

這是什麼

twoFactor 是 Better Auth skills 倉庫 下的 Agent Skill(目錄名 twoFactor,SKILL 元數據中的名稱爲 two-factor-authentication-best-practices)。它面向已在使用 Better Auth 的項目,說明如何配置服務端 twoFactor() 插件、客戶端 twoFactorClient(),以及啓用、登錄校驗、可信設備與關閉等完整生命週期。在 officialskills.sh 上歸類爲官方安全類 Skill,由 VoltAgent 團隊維護索引。

核心功能

以下能力均來自官方 Skill 文檔,對應 Better Auth twoFactor 插件行爲:

  • TOTP:對接身份驗證器應用;可配置位數(6 或 8)、週期(默認 30 秒);校驗時接受當前週期前後各一個時間窗的碼。
  • OTP:通過 sendOTP 自定義郵件或短信下發;可配置有效期、位數、單碼最大嘗試次數;庫內 OTP 存儲支持 plain、encrypted、hashed 或自定義加解密。
  • 備用碼(Backup codes):啓用 2FA 時自動生成,單次有效;支持密碼確認後重新生成(舊碼全部失效)。
  • 登錄流程:密碼登錄後若需 2FA,響應中帶 twoFactorRedirect: true,客戶端跳轉校驗頁;可用 TOTP、OTP 或備用碼完成,成功後建立會話。
  • 可信設備:校驗時傳 trustDevice: true,默認信任 30 天(trustDeviceMaxAge),每次登錄可刷新。
  • 安全相關:憑據校驗後先移除會話、再發臨時 2FA Cookie(默認 10 分鐘);2FA 端點內置限流(10 秒內 3 次);TOTP 密鑰與默認備用碼加密存儲;OTP 校驗使用恆定時間比較。
  • 限制:僅支持憑據(郵箱/密碼)賬號啓用 2FA;啓用與關閉均需密碼確認。

安裝與啓用

在支持 Agent Skills 的編碼助手中,可用官方給出的安裝命令(與 officialskills.sh 一致):

npx skills add https://github.com/better-auth/skills --skill better-auth-twoFactor

也可將 Skill 目錄鏈接交給助手安裝:https://github.com/better-auth/skills/tree/main/better-auth/twoFactor。

安裝 Skill 隻影響助手上下文,應用側仍需在項目中接入 Better Auth 插件並遷移數據庫。

服務端:在 betterAuth 配置中加入 twoFactor,並設置 issuer(顯示在驗證器應用中的發行方名稱):

import { betterAuth } from "better-auth";
import { twoFactor } from "better-auth/plugins";

export const auth = betterAuth({
  appName: "My App",
  plugins: [
    twoFactor({
      issuer: "My App",
    }),
  ],
});

客戶端:使用 twoFactorClient,在需要二次驗證時跳轉(示例爲 /2fa):

import { createAuthClient } from "better-auth/client";
import { twoFactorClient } from "better-auth/client/plugins";

export const authClient = createAuthClient({
  plugins: [
    twoFactorClient({
      onTwoFactorRedirect() {
        window.location.href = "/2fa";
      },
    }),
  ],
});

數據庫:使用內置 adapter 時執行:

npx auth@latest migrate

若使用 Drizzle 或 Prisma,按項目慣例 generate 並 push schema。驗證:用戶表應出現 twoFactorSecret 字段。

Cursor、Codex CLI、Claude Code 等對 npx skills add 的支持方式因產品而異;未在官方資料中單獨說明的差異此處不展開,以各工具當前 Skills 文檔爲準。

典型用法

爲用戶開啓 2FA

需先校驗密碼;返回 totpURI(用於生成二維碼)和 backupCodes。twoFactorEnabled 在首次 TOTP 校驗成功後纔爲 true(可用 skipVerificationOnEnable: true 跳過,官方不推薦)。

const enable2FA = async (password: string) => {
  const { data, error } = await authClient.twoFactor.enable({
    password,
  });

  if (data) {
    // data.totpURI — generate a QR code from this
    // data.backupCodes — display to user
  }
};

展示二維碼(示例使用 react-qr-code):

import QRCode from "react-qr-code";

const TotpSetup = ({ totpURI }: { totpURI: string }) => {
  return <QRCode value={totpURI} />;
};

完成 TOTP 綁定:

const verifyTotp = async (code: string) => {
  const { data, error } = await authClient.twoFactor.verifyTotp({
    code,
    trustDevice: true,
  });
};

郵件 OTP 作爲第二因素

在服務端配置 otpOptions.sendOTP,例如發郵件:

twoFactor({
  otpOptions: {
    sendOTP: async ({ user, otp }, ctx) => {
      await sendEmail({
        to: user.email,
        subject: "Your verification code",
        text: `Your code is: ${otp}`,
      });
    },
    period: 5,
    digits: 6,
    allowedAttempts: 5,
    storeOTP: "encrypted",
  },
});

客戶端發送與校驗:authClient.twoFactor.sendOtp();authClient.twoFactor.verifyOtp({ code, trustDevice: true })。

登錄時的 2FA 分支

  1. 調用 signIn.email({ email, password })
  2. 在 onSuccess 中檢查 context.data.twoFactorRedirect
  3. 若爲 true,進入 /2fa 等校驗頁
  4. 用 TOTP、OTP 或備用碼完成校驗
  5. 成功後寫入會話 Cookie
const signIn = async (email: string, password: string) => {
  const { data, error } = await authClient.signIn.email(
    { email, password },
    {
      onSuccess(context) {
        if (context.data.twoFactorRedirect) {
          window.location.href = "/2fa";
        }
      },
    }
  );
};

服務端直連 API 時,可檢查響應是否包含 twoFactorRedirect。備用碼恢復:authClient.twoFactor.verifyBackupCode({ code, trustDevice: true })。關閉 2FA:authClient.twoFactor.disable({ password }),並會撤銷可信設備記錄。

更完整的 issuer、totpOptions、backupCodeOptions、twoFactorCookieMaxAge、trustDeviceMaxAge 等組合見官方 Skill 中的 Complete Configuration Example。

適用場景與注意

適合:已在用 Better Auth、需要 TOTP 驗證器、郵件/短信 OTP、備用碼與「信任本設備」登錄體驗的 Web 或全棧應用;希望助手按官方字段與流程生成配置和客戶端調用,而不是手寫一套 TOTP。

注意:

  • 2FA 僅適用於郵箱密碼賬號;OAuth 等需另做設計。
  • OTP 下發依賴你實現的 sendEmail 或短信通道,Skill 不包含具體郵件服務商集成。
  • 生產環境應使用加密存儲 OTP/備用碼,並理解默認限流與 Cookie 超時,按需調整 twoFactorCookieMaxAge、allowedAttempts 等。
  • Skill 描述的是插件能力;具體框架(Next.js、React 等)的路由與 UI 仍需自行實現。

結尾

twoFactor Skill 把 Better Auth 雙因素認證的安裝、客戶端掛鉤、TOTP/OTP/備用碼與登錄分支寫成可檢索的步驟與代碼片段,適合在需要 MFA 時交給編碼助手對照實現,避免單因素或半成品 2FA 流程。官方目錄:https://github.com/better-auth/skills/tree/main/better-auth/twoFactor。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜