WebAuthn RFC
本文档旨在记录 Discourse 项目在 FIDO2 / WebAuthn 认证方面的目标。
为什么?
在 Discourse 中添加 WebAuthn 支持将提高用户账户的安全性,使人们能够利用设备的内置安全功能(如智能手机指纹识别器)轻松访问无需密码的账户。
认证方式
- WebAuthn 作为第二因素认证器(作为 Google Authenticator 的替代方案)
- WebAuthn 作为第一因素认证器(作为社交登录的替代方案)
- WebAuthn 作为多因素认证器(无用户名登录)
WebAuthn 作为第二因素认证器
这将允许已经拥有活跃账户的 Discourse 用户使用 WebAuthn 作为双因素认证(2FA),而目前我们仅支持 TOTP。
任何 WebAuthn 方法均可在此使用,无论是设备生物识别(Android 上的指纹识别器、Windows Hello 笔记本电脑)、设备安全芯片(TPM、安全飞地)还是硬件密钥(如 Yubikey)。
以下浏览器的所有用户均可使用此功能:
- Windows 上的 Microsoft Edge,使用 Windows Hello(支持面部识别、指纹识别器或 PIN 码)
- macOS 上的 Chrome,使用 Touch ID
- Android 手机
- 笔记本电脑/台式机/手机 + 物理密钥(Yubikey、Google Titan)
WebAuthn 作为第一因素认证器(无需密码的账户)
允许用户使用 WebAuthn 认证作为密码的替代方案登录其 Discourse 账户。如果已设置第一因素认证器,系统将提示用户使用该认证器而非密码。
第二因素认证所支持的相同认证方式(生物识别、安全芯片或硬件密钥)同样适用于第一因素认证。
注册流程
无密码字段
登录流程
WebAuthn 作为多因素认证器(无用户名登录)
将提供一种替代登录方式,仅提示输入 WebAuthn 信息。已注册的安全密钥还将向 Discourse 服务器传递用户 ID 信息。
此认证方式目前需要现代认证密钥(例如 Yubikey 5)以及 Google Chrome 76 及以上版本,因为它依赖于名为“驻留密钥”(Resident Keys)的功能。由于数据存储在认证器中,因此可能存在限制,例如 Yubikey 5C 最多只能存储 25 个此类密钥。
注册流程
这些流程是无密码登录流程的演进,而非独立的登录流程。这支持迭代式实施。
无密码字段,增加一个用于启用驻留密钥的额外复选框
登录流程
如果用户名留空,系统将尝试从认证器中获取
user_id
参考资料
演示
https://webauthndemo.appspot.com/
https://webauthn.io/dashboard
资源
https://medium.com/@herrjemand/introduction-to-webauthn-api-5fd1fb46c285
22 个赞
感谢提交这份 RFC,内容非常详尽!不过我想到一个问题:在常规用户名和密码登录流程中,将 WebAuthn 作为双因素认证(2FA)方法使用时,流程应如何设计?当我使用 TOTP 进行 2FA 登录时,会弹出如下模态框:
如果用户同时启用了 TOTP 和 WebAuthn 认证器,流程会怎样?用户是否需要在该模态框中选择使用 WebAuthn 还是 TOTP 令牌?或者这样会不会过于繁琐?也许 Discourse 可以默认优先提示用户进行 WebAuthn 认证(如果用户已设置且浏览器支持),若不可用再回退到 TOTP?
现有实现示例
Twitter:
GitHub:
Google 账户:
6 个赞
是的,这似乎正成为实施 WebAuthn 的标准方式,而且我非常喜欢这种登录流程。我确信我们也会朝这个方向前进。
7 个赞
谢谢你,Jeff,这说得通。经过进一步调查,今天还有几点想法:
第一因素认证
- 如果用户使用 Webauthn 作为第一因素认证方法注册 Discourse 账户,之后是否有办法改为使用密码?如果可以,他们设置的 Webauthn 认证是否会退化为常规的二次验证(2FA)方法,直到他们选择将其移除?
- 如果 Webauthn 被用作第一因素认证方法,它是否仍会显示在 UI 的二次验证偏好设置中,只是无法被移除?
- 是否也可以合理地认为,用户将被阻止像启用 2FA 时那样设置社交登录?
- 我推测,用户偏好设置中发送重置密码邮件的部分也会发生变化,因为使用第一因素认证的用户将没有密码:
6 个赞
sam
(Sam Saffron)
5
从文字角度来看,我不喜欢使用“Web Authn”这个术语,我认为这会让最终用户感到困惑,不如直接使用“安全密钥”之类的说法。
我非常希望暂时避免考虑“第一因素/无密码”认证的问题。对我们来说,必须先推出这项功能,并运行 3 到 4 个月,之后才考虑相关事宜。
特别是因为我们已经支持通过电子邮件登录,所以用户理论上可以忘记密码。
我同意流程应该是:如果你具备相关条件、拥有 API 以及 WebAuthn 密钥,则优先尝试 WebAuthn,但同时为用户提供退出选项。另外请注意,用户可能拥有多个 WebAuthn 设备,建议参考 Google 在此方面的处理方式(例如提供“选择其他选项”的链接)。
关于长期规划,我想到一个独立的事项:我们可以利用“Discourse 应用”来实现两步验证(2FA),这将会非常棒,@pmusaraj。这将使两步验证的普及程度大大提高。
14 个赞
Falco
(Falco)
6
是的,我同意。设计稿中的“webauthn”只是一个占位符。
不过,“安全密钥”这一说法无法传达用户可以使用笔记本电脑或手机上的指纹或摄像头进行认证的事实。
没错,文中提出的三种方法应按顺序实施,因为方法 1 相对简单,但能为方法 2 和 3 奠定基础。
6 个赞
Rafe
(Rafe)
8
关于“将 WebAuthn 作为第一因素身份验证器”,标准第二版正在讨论其中可能涉及的隐私问题:https://github.com/w3c/webauthn/pull/1250/
关于安全密钥的命名,我同意 RubyGems.org PR 中阐述的理由。
我还建议在安全密钥昵称之外,增加“上次用于登录的时间”戳,以帮助区分密钥并识别潜在恶意活动。
8 个赞
riking
(Kane York)
9
在我工作的地方(属于高安全环境),我们也有一个警报机制:如果安全密钥超过 90 天未被使用,系统会通过邮件提醒用户,提示其要么使用该密钥,要么将其从账户中移除。
我认为将这一机制的阈值设定为 360 天或许是个不错的主意?
7 个赞
Falco
(Falco)
10
好主意。如果间隔太短会很烦人,因为我们使用的是“无限期”会话,而且我认为大多数人会每天使用一个密钥,并在抽屉里备有一个备用密钥。这还不包括多台设备上原生的安全密钥。
6 个赞
我很高兴地宣布,我已合并了该功能的 PR,因此我们很快就能对 WebAuthn 进行非常非常彻底的测试了!
8 个赞
Falco
(Falco)
12
刚刚添加了 Android 指纹识别、通过 NFC 的 YubiKey 以及通过 USB-C 的 YubiKey,使用的是 Chrome Android 和 Firefox 桌面版,目前一切正常。
有个大 bug @Martin_Brennan @featheredtoast,在移动端视图中无法登录:
在桌面视图中则运行正常:
10 个赞
sam
(Sam Saffron)
13
一些随机的反馈 
这看起来不太对:
我们应该参考 Composer 中的边距和“取消”按钮的颜色。
“密码重置邮件”这个说法感觉不太合适,似乎不属于这里。
或许可以改成?
继续 取消
忘记密码? ← 浅灰色显示
密码输入框看起来太大了,应该稍微小一点。
这里应该显示“移除”或“删除”。
如果你尝试添加一个已经添加过的 YubiKey,会出现一个晦涩的错误提示。
整体来说:

9 个赞
啊,我就知道我在审查中漏掉了一个路由。发现得好 
我想这种情况已经持续一段时间了,不过这些确实是很好的改进。
同意,这是个很好的改动。
也许我们可以直接复用 Chrome 内置的文案?“您已注册此安全密钥,无需再次注册。”这段文案清晰明了。
9 个赞
感谢 @Falco 和 @sam 的反馈。我此前也没意识到移动端登录还有另一条路径!我今晚将开始着手修复这些问题,包括密码标签和按钮的更改,希望能尽快提交一个新的 PR 来解决!
7 个赞
很高兴这也能在你的安卓设备上运行(尽管移动端视图尚未正常工作)——我之前没有安卓设备用于测试。
6 个赞
我不确定我是否准备好回到安卓系统了——我太爱我的 iPhone 8 了 
5 个赞
谁说返回?那是旧时代的思维!现代人可拥有多台设备;)
8 个赞