Bedrud 文档

Bedrud 支持多种认证方式。

JWT(JSON Web Tokens)

Bedrud 使用 JWT 进行会话管理。登录时,服务器返回两个令牌:

  1. Access Token: 短期有效(例如 1 小时)。用于访问受保护的 API 端点。
  2. Refresh Token: 长期有效(例如 30 天)。用于在无需重新登录的情况下获取新的 Access Token。

后端在 internal/middleware/auth.go 文件中验证这些令牌。

令牌管理与安全性

1. 令牌对策略(Rotation)

Bedrud 使用安全的令牌轮换策略。用户认证时,会收到:

  • Access Token: 使用 HS256 签名,包含用户 ID、名称和权限。有效期较短(通过 tokenDuration 配置)。
  • Refresh Token: 一个独立的长期令牌。

轮换机制: 当 Access Token 过期时,客户端将 Refresh Token 发送到 /api/auth/refresh。服务器随后签发一对全新的令牌,并更新数据库中存储的 refresh token。即使令牌被盗,这也限制了可利用的时间窗口。

2. 令牌撤销(Blacklisting)

为了支持安全的登出,Bedrud 实现了令牌黑名单

  • 当用户登出时,其当前的 Refresh Token 会被添加到 blocked_refresh_tokens 表中。
  • 在刷新任何会话之前,服务器会检查此表。如果令牌已被阻止,请求将立即被拒绝。
  • 后台任务(Scheduler)负责在这些被阻止的令牌自然过期后进行清理。

3. JWT Claims 结构

令牌携带元数据,允许后端和前端无需查询数据库即可快速做出决策:

{
  "userId": "uuid-string",
  "email": "user@example.com",
  "name": "Display Name",
  "accesses": ["user", "admin"],
  "exp": 123456789,
  "iat": 123456780
}

认证方式

1. 邮箱密码登录

  • 密码使用 bcrypt 进行哈希处理—从不以明文存储。
  • 注册时,会在数据库中创建新的用户记录。

2. 社交登录(OAuth2)

Bedrud 使用 Goth 库支持:

  • Google
  • GitHub
  • Twitter

你可以在 config.yaml 中填写 auth: 部分的 Client ID 和 API Secret 来启用它们。

3. Passkeys(WebAuthn/FIDO2)

Bedrud 通过 FIDO2 标准(WebAuthn)支持无密码认证。

  • 注册流程:
    1. 开始: 服务器生成一个加密安全的 Challenge 并将其存储在用户会话中。
    2. 完成: 客户端的 authenticator(如 TouchID、YubiKey)对 challenge 进行签名。服务器验证 attestation,提取公钥,并将其保存在 passkeys 表中。
  • 认证流程:
    1. 开始: 服务器签发一个新的 challenge。
    2. 完成: 客户端使用私钥对 challenge 进行签名。服务器从数据库中检索公钥,验证签名,并检查签名计数器
  • 安全性: Counter 字段的匹配可以防止重放攻击。如果 authenticator 的计数器不高于存储的计数器,则登录将被拒绝。

4. 访客登录

允许用户仅通过输入名称即可立即加入会议。服务器创建一个具有 guest 角色的临时用户记录。

电子邮件验证

当配置中 requireEmailVerification: true 时,本地(非OAuth)注册和登录需要电子邮件确认:

  • 注册 创建用户但将 EmailVerifiedAt 设置为 nil。用户必须验证后才能登录。
  • 登录 对未验证账户返回 403{"requiresVerification": true}
  • 重新发送 通过 POST /api/auth/verify/resend — 受 verificationEmailCooldownMins 和单独的速率限制桶(authResendMaxRequests)限制。
  • 自动清理unverifiedAccountTTLHours(默认48小时,0为禁用)后删除未验证账户。
  • 修改邮箱 触发新的验证流程。用户保持登录状态;颁发新令牌。

访客用户例外——他们没有电子邮件。

密码重置

密码重置流程(需要SMTP):

  1. POST /api/auth/forgot-password 带上 {"email": "..."} — 服务器发送重置链接到邮箱
  2. POST /api/auth/reset-password 带上 {"token": "...", "newPassword": "..."} — 设置新密码

重置令牌TTL由 resetTokenTTLHours 控制(默认1小时)。forgot-password端点共享认证速率限制桶。

冷却与速率限制

Bedrud 使用四个独立的速率限制桶:

端点默认值窗口
认证login, register, refresh, passkey, forgot-password1060s
访客guest-login560s
API通用API3060s
重新发送verify/resend360s

桶设置为 0 = 禁用。所有限制按远程IP计算。超出限制的请求返回 429 Too Many RequestsRetry-After 头部。

互操作性与 CORS

Bedrud 设计为可从多个来源访问,这对于开发环境(React 开发服务器)和生产环境(不同子域名)至关重要。

  • CORS 策略:config.yaml 中定义。它支持 AllowCredentials: true,这是 OAuth 和 Passkey 流程中使用的会话 cookie 所必需的。
  • 允许的来源: 默认情况下,允许服务器自身的域名和 localhost:3000(React 开发服务器端口)。

用户角色(访问控制)

每个用户都有一个 accesses 数组,可以同时包含多个访问级别。JWT claims 中包含完整的 accesses 数组,允许中间件检查细粒度权限。

访问级别

访问级别范围授予权限
superadmin系统级完整访问管理仪表板(/dashboard/admin)、所有管理 API endpoint(/api/admin/*)、用户管理、房间管理、系统设置、邀请令牌。作为所有房间管理操作的全局绕过。由 RequireAccess("superadmin") 中间件保护。
admin已定义,未强制执行可在 accesses 数组中使用,但当前未被任何中间件使用。仅用于信息标识。保留用于未来的基于角色的访问控制功能。
moderator房间级可在特定房间内进行管理:禁言聊天、关闭/开启参与者音频、聚光灯、停止屏幕共享、禁用视频。由房间创建者或 superadmin 在通话中通过 PromoteParticipant 提升。通过 isRoomModerator() 辅助函数检查。
user标准所有注册用户的默认级别。可创建房间、加入房间、管理个人资料和管理自己的通行密钥。由 Protected() 中间件保护。
guest受限用于通过访客登录加入公共房间的临时用户。无法创建房间或访问受保护的功能。

角色层级

superadmin > admin > moderator > user > guest

superadmin 可以在任意房间中执行任何管理操作,而无需被提升为房间 moderator。房间创建者自动成为房间管理员,并可将参与者提升为 moderator。

角色分配

角色通过多种渠道管理:

  • CLI: bedrud user create(创建为 user)、bedrud user promote(添加 superadmin)、bedrud user demote(移除 superadmin
  • 管理仪表板: 用户详情页面有提升/降级按钮
  • 管理 API: PUT /api/admin/users/:id/accesses,携带所需的 accesses 数组
  • 会议中: 房间创建者可将参与者提升为房间级 moderator

注意: 没有用于创建首个 superadmin 的 API endpoint 或 Web UI。安装后,您必须使用 CLI(bedrud user create + bedrud user promote)来引导初始管理员访问。这是一项有意的安全措施。