1772 字
9 分钟
Auth api设计详解
2024-10-28

The Copenhagen Book#

这本书是 Lucia 作者大佬 pilcrow 写的开源指南,围绕“如何把身份认证做对”展开。我按照书中章节脉络,结合在实际项目里踩过的坑,总结一份适合日常后端开发与产品协作的备查表。

以下内容覆盖:

  • 身份模型(用户、身份、会话)如何拆分;
  • 凭证存储与秘密管理;
  • 注册/登录/忘记密码等基础流程;
  • 多因素认证(MFA)、WebAuthn、第三方登录;
  • 会话管理、切换设备、注销策略;
  • 管理后台与自建 OAuth Provider;
  • 审计日志、风控、隐私合规。

核心实体模型#

The Copenhagen Book 把身份系统拆成三层,可避免“把所有逻辑塞进 user 表”:

实体说明常见字段
用户 (users)代表真实的个人或组织,提供业务上下文id, display_name, created_at, banned_at
身份 (identities)每种登录方式的唯一标识id, user_id, provider_id, provider_user_id, created_at
会话 (sessions)某次登录状态,可跨设备id, user_id, active_expires, idle_expires, user_agent, ip

设计关键点:

  • 用户可以拥有多个身份:邮箱密码、GitHub OAuth、手机号等。
  • 身份与用户是 1;会话与用户也是 1
  • 会话应该存储 IP、 User-Agent、最近活动时间,便于风控与用户自助管理。
  • 不要把密码、第三方 token、WebAuthn credential 混入用户表,分开存储才能实现更细的权限与轮换策略。

凭证存储与秘密管理#

密码#

  • 使用 bcryptargon2id 等现代算法,设置合理代价(如 argon2id time_cost=3, memory=64MB)。
  • 永远不要明文存储,也不要“自创盐”,库已经处理。
  • 存储额外字段:password_version(调整参数或算法时逐步迁移)、last_rotated_at
  • 登录成功后如果检测到 hash 版本过旧,后台静默升级(rehash-on-login)。

OTP 与重置码#

  • 一次性验证码/重置码使用 uuidcrypto.randomBytes 生成,存储哈希值(sha256)。
  • 记录 expires_atconsumed_at,用数据库唯一约束防止并发使用。
  • 邮件/短信里不要包含用户 ID,用 token 换取身份。

JWT/Session Secret#

  • 密钥统一放在 Secret Manager(Vault、AWS Secrets Manager);禁用硬编码。
  • 轮换策略:生成新密钥、让旧密钥在合理宽限期内仍可验证(kid 机制)。
  • Server-side session 存数据库或 Redis 时,同步记录 IP/UA,异常时可以踢出。

注册流程最佳实践#

  1. 前端校验:限制密码强度、邮箱格式,但不要过度暴露错误信息。
  2. 速率限制:邮箱注册/验证码接口需做 Rate Limit + Captcha。
  3. 邮箱验证:注册时生成 email verification token,允许账号未验证时有限操作(如仅能登录一次提醒验证)。
  4. 邀请制:提前创建 invitation 记录,关联 inviter_idaccepted_at,控制注册入口。
  5. 事务处理:创建用户、身份、发送验证邮件在事务中完成,失败时回滚。

登录流程#

基础邮箱+密码#

  • 返回错误时统一提示“凭证错误”,避免区分“用户不存在”或“密码错误”。
  • 支持 remember me:idle_expires 设置为 7-30 天,并通过 httpOnly + Secure Cookie 存储会话 ID。
  • 登录成功写入审计日志(login_success),包括设备指纹。

多因素认证(MFA)#

  • 支持 TOTP(Authenticator App)和备份代码(Backup Codes)。
  • TOTP 种子加密存储(可用 KMS 包裹)。
  • 绑定流程:显示二维码 → 输入 6 位验证码确认 → is_primary_mfa 标记。
  • 登录流程:先验证主凭证,再要求 2FA;允许“信任设备”7-30 天,通过 mfa_remember_token 标记。
  • 恢复:备份代码一次性使用;客服通道需严格验证身份。

WebAuthn / Passkeys#

  • 存储 WebAuthn credential 时记录 credential_id, public_key, transports, sign_count
  • 对于 passkey,允许跨设备同步,不要绑定特定浏览器。
  • WebAuthn 可作为无密码登录方式,也可作为 2FA。

第三方登录(OAuth/OIDC)#

  • 创建 oauth_providers 表记录配置信息(client_id、scopes、redirect URI)。
  • 将 provider 返回的 sub/id 等唯一标识与 identities 表关联。
  • 若用户首次使用第三方登录,需要流程:
    • 找到与邮箱匹配的用户 → 提示合并或拒绝;
    • 无匹配时创建新用户(可直接标记邮箱已验证)。
  • 定期刷新 access_token/refresh_token;失效时告知用户重新授权。

会话管理#

  • 单点登录/多设备:允许多个活跃 session;提供“查看并注销其他设备”功能。
  • 活跃检测active_expires 表示 token 有效期,idle_expires 表示最大不活跃时间。
  • 注销:服务端删除 session 记录,删除 cookie/localStorage;对于 JWT 需维护 denylist 或缩短过期时间。
  • Remembered Device:存储在 trusted_devices 表,包含指纹、首次信任时间、最后使用时间。
  • Session Fixation:登录成功后一定要 rotate session ID。

API 设计示例#

POST /auth/register
POST /auth/login
POST /auth/logout
POST /auth/refresh
POST /auth/mfa/setup
POST /auth/mfa/verify
POST /auth/password/request-reset
POST /auth/password/reset
GET  /auth/sessions
DELETE /auth/sessions/{sessionId}

返回格式建议统一:

{
  "session": {
    "id": "sess_123",
    "expiresAt": "2025-05-01T00:00:00Z"
  },
  "user": {
    "id": "user_456",
    "displayName": "Alice",
    "hasMfa": true
  }
}

错误响应包含 code(内部追踪)与 message(给用户),必要时加 metadata

{
  "code": "AUTH_INVALID_TOTP",
  "message": "验证码无效或已过期,请重试",
  "metadata": {
    "remainingAttempts": 3
  }
}

管理后台与支持流程#

  • 管理后台应具备:搜索用户、查看身份信息、重置密码、禁用账号、强制注销等能力。
  • 所有敏感操作(禁用、冻结资金)必须记录审计日志,含操作者 ID 与理由。
  • 支持团队需要明确定义升级流程:例如社交账号被盗、设备遗失、申诉流程。

风险控制与检测#

  • 登录异常检测:同一账号在短时间内不同国家登录、IP 风险评分。
  • 密码喷射(password spraying):统计不同邮箱的失败次数,整体限流。
  • 设备指纹:可以使用指纹库或自定义 UA + 分辨率 + Canvas 指纹(注意隐私合规)。
  • 风控触发时增加验证因素(Step-up Auth),例如要求验证码或 2FA。

审计与隐私#

  • 审计日志表存储:event, user_id, session_id, actor_id, ip, user_agent, metadata, created_at
  • 遵守最小化原则:只收集必要数据,设定数据保留期限(GDPR、CCPA)。
  • 提供数据导出与删除接口(Data Subject Request)。
  • 避免在日志里记录敏感信息,如密码或完整 token。

常见坑位与应对#

  • 跨域 Cookie 失效:确保设置 SameSite=NoneSecure,以及后台与前端域名一致。
  • CSRF:推荐使用 SameSite Cookie + 双提交 Cookie 或 CSRF Token。
  • 验证码滥用:引入滑块、人机验证服务,或对高危 IP 拦截。
  • 缓存问题:包含授权信息的响应 header 应禁用 CDN 缓存。
  • 时钟漂移:TOTP 校验容忍 ±30s;服务部署多地区需同步 NTP。

推荐工具与库#

  • Lucia:TypeScript 生态下的身份框架,书中示例基于它。
  • NextAuth.js / Auth.js:前端友好的 Next.js 解决方案。
  • Ory / Supabase Auth:托管身份平台,适合 MVP。
  • FGA / CASL:做细粒度授权(Access Control)。
  • Temporal / Q Stash:处理邮件发送、密码重置等异步任务。

进一步阅读#

Auth api设计详解
https://bangwu.top/posts/web-auth/
作者
棒无
发布于
2024-10-28
许可协议
CC BY-NC-SA 4.0