OTP + Google 登录指南

December, 23rd 2025 4 min read Markdown
OTP + Google 登录指南:better-auth 实现

本文汇总当前分支未提交的 OTP 邮箱验证码登录相关改动,便于后续维护或复查。内容仅包含实现思路和代码位置,不包含任何敏感信息。

核心改动概览

  • 客户端切换到 better-auth 的 email-otp 流程,放弃 magic link。
  • 前端登录表单支持 Google 登录 + 邮箱验证码两步流程,带倒计时、重发与错误提示。
  • 服务端启用 emailOTP 插件,配置发送验证码邮件、过期时间与速率限制。
  • 新增验证码邮件模板(中文),支持登录/邮箱验证/重置密码场景。

客户端(登录表单)

文件:src/client/components/auth/login-form.tsx

  • 状态机:step: "request" | "verify";倒计时、错误提示、邮箱/验证码输入。
  • 持久化:邮箱、步骤、redirect、倒计时写入 localStorage + sessionStorage;同时同步到 URL 查询参数 otpEmail/otpStep/redirect,即使刷新或被重定向回 /login 也能继续输入验证码。
  • 错误提示:捕获 Invalid OTP/OTP expired 等返回,转为中文提示,并保留在验证步骤。
  • 安全:redirect 仅允许同源相对路径(防止开放跳转)。
  • 手动切回邮箱输入时清理本地 OTP 状态。

辅助方法:requestEmailOtpsignIn.emailOtp 来自 src/client/lib/auth.ts,该文件使用 emailOTPClient 插件创建 better-auth 客户端。

服务端(better-auth 配置)

文件:src/server/lib/auth.ts

  • 插件:emailOTP({ otpLength: 6, expiresIn: 10*60, sendVerificationOTP })
  • 发送逻辑:sendVerificationOTP 调用邮件工具 emailSender.sendOtpCode,并记录日志。
  • 速率限制:/email-otp/send-verification-otp 5 分钟内最多 3 次;/sign-in/* 5 分钟 5 次。
  • 开放路由:src/server/config/routes.ts/api/auth/email-otp/* 列入公开名单(Better Auth 内部校验)。

邮件发送与模板

文件:

  • src/server/lib/email/sender.ts:新增 sendOtpCode,复用 Resend 客户端。
  • src/server/lib/email/templates/otp-code.ts:中文模板,区分场景文案(登录/验证邮箱/重置密码),附带有效期提示与安全提示。
  • src/server/lib/email/types.ts:补充 OTP 类型定义。
  • src/server/lib/email/index.ts:导出新模板。

关键路由配置

文件:src/server/config/routes.ts

  • PUBLIC_API_ROUTES 添加 /api/auth/email-otp/*,便于前端无会话请求验证码、验证登录。

使用步骤(端到端)

  1. 客户端输入邮箱,点击“发送验证码” → 调用 requestEmailOtp(email)/api/auth/email-otp/send-verification-otp
  2. 收到邮件中的 6 位验证码,在同一或新页面输入;URL 若含 otpEmail/otpStep=verify 会自动恢复状态。
  3. 提交验证:signIn.emailOtp({ email, otp })/api/auth/sign-in/email-otp;成功后按安全处理过的 redirect 跳转。
  4. 错误/过期:前端展示中文提示,保留验证步骤,允许重试或重发。

参考文件列表

  • 客户端逻辑:src/client/components/auth/login-form.tsx
  • Auth 客户端创建:src/client/lib/auth.ts
  • Auth 服务端配置:src/server/lib/auth.ts
  • 公共路由白名单:src/server/config/routes.ts
  • 邮件发送与模板:src/server/lib/email/sender.tssrc/server/lib/email/templates/otp-code.tssrc/server/lib/email/types.ts
  • 其它文档:docs/项目全览-zh.md(仅有一处新增公开路由描述)

验证点

  • 前端:错误验证码提示为中文;刷新/重定向后仍停留在验证码步骤;重发冷却与倒计时正常。
  • 服务端:验证码邮件可发送,10 分钟内有效;速率限制生效;redirect 同源校验通过。
  • 安全:外部跳转被拒绝,所有 OTP 请求均为公开路由但由 better-auth 校验邮箱/验证码。