spinny:~/writing $ vim passkeys-webauthn-passwordless-authentication.md
1~2密码是我们标准化的事物之一,因为我们已经使用它们多年了。用户会忘记它们、重复使用它们、将它们写在不该写的地方。团队必须管理重置、策略、哈希、泄漏、网络钓鱼和支持。3~4passkey 并没有使身份验证变得完美,但它们消除了一个巨大的问题:服务器不再需要保留与用户共享的秘密。5~6## 到底发生了什么7~8passkey是基于WebAuthn的凭证。当用户创建时,设备会生成一个密钥对:9~10- 私钥,保留在设备或密码管理器中;11- 服务器可以保存的公钥。12~13登录服务器时不会询问“告诉我密码”。发送随机挑战。设备使用私钥对其进行签名。服务器使用公钥验证签名。14~15这是很好的部分:如果数据库被盗,里面没有密码可以破解。如果用户最终进入假域名,则 passkey 对于该域名无效。这不仅仅是方便,更是针对网络钓鱼的具体保护。16~17## 浏览器充当桥梁18~19在浏览器中,两个主要的 API 是:20~21- `navigator.credentials.create()` 创建passkey;22- `navigator.credentials.get()` 在登录时使用它。23~24但重要的逻辑是在服务器上。服务器必须生成质询,暂时保存,验证响应,检查源和Relying Party ID,然后创建会话。25~26客户端部分应该几乎很无聊:27~28```typescript29const options = await fetch('/api/passkeys/login/options').then((r) => r.json());30~31const credential = await navigator.credentials.get({32 publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(options),33});34~35await fetch('/api/passkeys/login/verify', {36 method: 'POST',37 headers: { 'Content-Type': 'application/json' },38 body: JSON.stringify(credential?.toJSON()),39});40```41~42如果您发现自己手动实施WebAuthn加密,请停止。使用强大的服务器端库。这里的错误不是“可爱的错误”,它们是身份验证漏洞。43~44## 数据库中保存的内容45~46没有必要拯救半个世界。通常就足够了:47~48- 凭证的ID;49- 公钥;50- 连接的用户;51- 任何验证计数器或元数据;52- 传输(如果对用户体验有用的话);53- 用户选择的名称;54- 创建日期和最后使用。55~56最小的表可能如下所示:57~58```sql59create table passkey_credentials (60 id uuid primary key default gen_random_uuid(),61 user_id uuid not null references users(id),62 credential_id text not null unique,63 public_key text not null,64 name text,65 created_at timestamptz not null default now(),66 last_used_at timestamptz67);68```69~70然后我会添加审核日志和通知:如果有人在我的帐户上创建了新的passkey,我想知道它。71~72## 用户体验比演示更重要73~74passkey 的演示总是很漂亮:你点击,Face ID,你就进去了。实际产品更复杂。75~76有人换手机了有人使用锁定的公司计算机。有些人不明白为什么浏览器会建议passkey。有人失去了对其设备的访问权限。77~78这就是为什么我不会以“从今天起不再为每个人提供密码”开始。我会这样开始:79~801. passkey内部用户可选;812.建议登录成功后创建一个;823.账户页面重命名和删除passkey;834. 明确的后备方案;845.在主登录中逐步推出。85~86界面中的文字应该简单。 “使用设备的锁定屏幕”比“使用居民 FIDO2 凭据进行身份验证”更好。87~88## 我会避免的错误89~90不要给客户带来挑战。质询是在服务器上创建的,并且只需验证一次。91~92不要只相信凭证 ID。您需要验证签名、质询、来源和Relying Party ID。93~94在拥有良好的恢复流程之前,请勿删除后备。无密码不一定要变成“如果你丢失了手机,你就永远出局”。95~96不要将 passkey 视为纯粹的前端按钮。隐藏按钮并不安全:真正的验证是在服务器端。97~98## Passkey-优先还是passkey-友好?99~100对于新产品,您可以首先考虑passkey。对于现有的应用程序,我更喜欢passkey友好:添加passkey作为推荐方法,衡量成功和问题,然后冷静地减少密码权重。101~102感觉不到理想的迁移。用户发现登录变得更加容易,而不是公司改变了其身份验证协议。103~104## 结论105~106passkey 很有趣,因为它们同时提高了安全性和用户体验,这是罕见的。它们不是魔杖:恢复、兼容性、支持和推出仍有待精心设计。107~108但基本的变化是强烈的。停止要求用户发明和保护秘密。您让设备签署与您的域相关的加密证明。更少的人类记忆、更少的网络钓鱼、更少的密码重置。我想说它们值得认真对待。109~110## 来源111~112- [MDN: Passkeys](https://developer.mozilla.org/en-US/docs/Web/Security/Authentication/Passkeys)113- [MDN: Web Authentication API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API)114- [W3C: Web Authentication](https://www.w3.org/TR/webauthn-3/)115- [passkeys.dev](https://passkeys.dev/)116~
NORMAL · passkeys-webauthn-passwordless-authentication.md [readonly]116 lines · :q to close