跳转到内容

认证与安全模型

SyncTV 把安全边界拆成几层:

  • 用户认证:密码、OPAQUE、WebAuthn/passkey、TOTP、恢复码、邮箱验证码和 OAuth2。
  • 用户 2FA:用户可选开启,必须拥有至少两种本地验证方式。
  • 访问 token:登录完成后签发,用于 HTTP/gRPC 业务 API。
  • management 控制面:CLI 使用的管理端点,独立于普通用户 token。
  • Provider 上游访问:Provider 自己决定上游 header 和凭据,不由 proxy 猜测客户端 header。
  • 集群内部认证:节点间 gRPC 使用 cluster.secret
认证与 2FA 边界图,展示本地第一因素、MFA 会话、OAuth2、token、业务 API 和 management 控制面的关系。认证与 2FA 边界图,展示本地第一因素、MFA 会话、OAuth2、token、业务 API 和 management 控制面的关系。
本地登录和 OAuth2 是不同信任路径。开启 2FA 后,本地登录需要完成第二因素;OAuth2 不计入本地 2FA,但可以独立签发可接受的登录上下文。
登录方式 可作为第一因素 可作为第二因素 说明
密码/OPAQUE 仅当服务端返回 MFA_METHOD_PASSWORD 时可用 OPAQUE 登录不等同于 password MFA verifier
WebAuthn/passkey 需要启用 WebAuthn 配置并完成绑定
TOTP 身份验证器 使用 SHA-1、6 位验证码和 30 秒周期;服务端必须配置 security.totp_encryption_key
TOTP 恢复码 每个恢复码只能使用一次;恢复码属于 TOTP 因素,不单独计为一种本地验证方式
邮箱验证码 依赖 SMTP 和验证码发送能力
OAuth2 OAuth2 不参与本地 2FA,但 2FA 用户可以直接用 OAuth2 登录

用户开启 2FA 前,系统会确认至少有两种可用的本地验证方式。开启后,使用本地单因素方式登录会进入 MFA 会话,客户端需要根据返回的剩余验证方式完成第二步。

开启 2FA 后,系统不应该接受旧的单因素 refresh token 继续刷新会话。满足 2FA 或 OAuth2 登录路径后签发的 token 会带有可接受的认证上下文。

实际语义:

  • 用户未开启 2FA:普通本地登录、MFA 后登录、OAuth2 登录签发的 token 都可按正常规则使用。
  • 用户开启 2FA:本地登录必须完成第二因素;refresh token 必须来自 MFA 后或 OAuth2 上下文。
  • 用户关闭 2FA:普通单因素和 MFA/OAuth2 上下文都可继续使用,直到 token 自身过期或被吊销。

本地第一因素成功后,如果需要第二因素,服务端不会直接签发最终 token,而是创建一个短期 MFA 会话。

客户端需要:

  1. 完成第一因素登录请求。
  2. 如果响应要求 MFA,读取可用的剩余验证方式。
  3. 如果剩余方式包含邮箱验证码,直接调用发送验证码接口。
  4. 如果剩余方式包含 MFA_METHOD_TOTP,调用 VerifyMfaTotp
  5. 如果剩余方式包含 MFA_METHOD_RECOVERY_CODE,调用 VerifyMfaRecoveryCode
  6. 使用 MFA 会话 ID 和第二因素证明完成登录。
  7. 保存最终 access/refresh token。

失败的 password、TOTP 和恢复码验证会进入对应的暴力破解保护。TOTP 和恢复码共享用户级失败计数,并结合客户端 IP 执行限制。

服务端生成 20 字节随机 TOTP secret,并通过 otpauth:// URI 返回给客户端。客户端使用该 URI 生成二维码,也可以显示响应中的 secret 供用户手动输入。绑定流程有 10 分钟期限;用户必须提交一个有效 TOTP 验证码,服务端才会确认凭据并返回恢复码。

服务端用 security.totp_encryption_key 加密 TOTP secret,并把用户 ID 放入密文上下文。验证码验证接受当前 30 秒时间步及相邻时间步。服务端记录最近使用的时间步,同一验证码不能在登录和敏感操作之间重复使用。生产主机应启用 NTP 或 chrony,避免时钟偏差超出验证窗口。

绑定完成后,服务端返回 10 个恢复码。服务端保存恢复码哈希并丢弃明文;客户端应要求用户保存这些恢复码。重新生成会使旧恢复码全部失效,成功验证一个恢复码后,服务端会删除该恢复码。

开始绑定、重新生成恢复码和删除 TOTP 都需要一次有效的敏感操作验证。删除 TOTP 会减少一种本地验证方式;如果删除后无法保留两种本地验证方式,用户必须先关闭 2FA。每个敏感操作验证 ID 只能使用一次。

用户偏好用于用户级配置,其中 two_factor_enabled 是安全敏感字段。

约束:

  • 开启 2FA 前必须有至少两种可用本地验证方式。
  • TOTP 与它的恢复码共同计为一种本地验证方式。
  • 删除 passkey、解绑邮箱或删除 TOTP 时,如果 2FA 已开启,操作后仍必须保留至少两种可用本地方式。
  • 管理员修改用户偏好时必须遵守角色层级,普通 admin 不能越权修改 root 或同级高权限用户。

management gRPC 是 CLI 和运维命令使用的控制面。

生产规则:

  • 优先使用 Unix socket。
  • 如果使用 TCP,必须设置 management.auth_token
  • 不要把 management TCP 端点暴露到公网。
  • 通过文件或 secret manager 注入 token。
  • management.enable_reflection 生产默认关闭。

management token 不是普通用户 access token。它代表运维控制面权限,应按基础设施 secret 管理。

Provider 负责决定上游请求 header。proxy 层只执行 Provider 给出的配置。

这意味着:

  • 原始客户端 RangeAcceptUser-Agent 等 header 不会被 proxy 自动转发。
  • 如果上游需要 Range,Provider 必须显式选择。
  • 如果直连 URL 绑定了 User-Agent,Provider 返回给客户端的 header 应与服务端代理 header 保持一致。
  • 客户端无法设置所需 header 时,应使用代理模式。

Provider 凭据配置见 媒体 Provider;客户端如何选择直连、代理和播放信息见 播放与代理

  • 安全与密钥: 配置 JWT、OPAQUE、Provider 凭据加密、密码复杂度、CORS 和可信代理。
  • 邮件与 OAuth2: 配置邮箱验证码、SMTP 和运行时 OAuth2 provider 配置。
  • WebAuthn: 配置 passkey 的 RP ID、origin、允许 origin 和 challenge 超时。
  • 限流: 配置 HTTP、gRPC、聊天、WebSocket 和认证相关限流。