认证端点 API
OTP 验证码发送端点,提供带频率限制和审计记录的验证码代理转发功能。
基础路径
/auth认证方式
公开接口,无需 JWT 认证。由后端统一做频率限制后代理转发到 Supabase Auth。
限流说明
- 全局限流:继承全局 CORS 中间件
- Auth 专用限流:额外的频率限制(由
site_settings动态配置) - IP 维度限流:数据库级每小时限制
- 邮箱维度限流:原子化 advisory lock 限流(消除 TOCTOU 竞态)
端点列表
POST /auth/send-otp
发送 OTP 验证码邮件。支持首次发送和重发(通过 resend_token)。
请求体
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
email | string | 是 | 目标邮箱地址 |
resend_token | string | 否 | 上次返回的一次性重发令牌,用于绕过冷却期重发 |
成功响应 200
json
{
"success": true,
"message": "验证码已发送",
"resend_token": "uuid-token",
"token_expires_at": "2026-01-01T00:05:00Z",
"retry_after": 60,
"next_allowed_at": "2026-01-01T00:01:00Z"
}| 字段 | 类型 | 说明 |
|---|---|---|
resend_token | string | 新的一次性重发令牌(用于下次重发) |
token_expires_at | string | 令牌过期时间(ISO 8601) |
retry_after | number | 距下次可发送的秒数 |
next_allowed_at | string | 下次可发送的 ISO 时间 |
错误响应
| 状态码 | error 值 | 说明 |
|---|---|---|
| 400 | invalid_body | 请求体格式无效 |
| 400 | invalid_email | 邮箱格式无效 |
| 400 | token_email_mismatch | 重发令牌与邮箱不匹配 |
| 429 | rate_limited | 请求过于频繁,返回 retry_after 和 next_allowed_at |
| 500 | internal_error | 服务暂时不可用 |
| 500 | send_failed | 验证码发送失败 |
限流响应 429
json
{
"success": false,
"error": "rate_limited",
"message": "请求过于频繁,请稍后再试",
"retry_after": 60,
"next_allowed_at": "2026-01-01T00:01:00Z"
}安全机制
- IP 获取:优先使用
x-real-ip(反向代理设置),fallback 到x-forwarded-for首个 IP - 日志脱敏:邮箱和 IP 在日志中自动脱敏(SHA-256 hash)
- 多层限流:内存限流中间件 + IP 数据库限流 + 邮箱原子限流
- 发送失败回滚:Supabase OTP 发送失败时自动回滚占位记录,避免冷却期误拦截