Highlight
Automatic passkey upgrades 让用户在用密码登录后,系统自动在后台创建 passkey 并通过通知告知,无需中断用户操作流程。
核心内容
今天的登录体验往往很繁琐:输入用户名、输入密码、等待短信验证码、再输入验证码——多步流程虽提升了安全性,但也很慢。很多 App 会在登录后弹出一个 upsell 界面问”要不要创建 passkey?“,但用户往往忽略或拒绝。
WWDC 2024 引入了 automatic passkey upgrades,完全改变了这个流程。用户正常用密码登录后,系统在后台自动创建 passkey 并弹出一个通知:“已为您创建 passkey”。下次登录时只需一次点击。整个过程中没有任何中断式的 upsell 界面。
Session 指出,预防钓鱼的最好方式是让账号没有任何可被钓鱼的认证因素。密码、SMS、邮件验证码、push 通知、TOTP——这些都可以被钓鱼。真正的目标是最终消灭所有可被钓鱼的因素,而 passkey 是通往这一目标的第一步。
详细内容
Automatic passkey upgrades 的实现原理
系统在处理自动升级请求时会进行一系列检查(04:18):
- 系统内部检查:设备是否设置了凭证管理器并支持自动升级?设备是否设置了密码?
- Web 特定检查:是否是非隐私浏览标签页?
- 凭证管理器条件:最重要的条件是——该管理器刚才是否刚刚填入了该账号的用户名和密码?
如果所有条件都满足,系统返回新创建的 passkey,设备显示通知。如果条件不满足,返回错误,但不显示任何 UI。
iOS/macOS 实现
传统的 upsell 方式是这样的(01:19):
// Offering a passkey upsell
func signIn() async throws {
let userInfo = try await signInWithPassword()
guard !userInfo.hasPasskey else { return }
let provider = ASAuthorizationPlatformPublicKeyCredentialProvider(
relyingPartyIdentifier: "example.com")
guard try offerPasskeyUpsell() else { return }
let request = provider.createCredentialRegistrationRequest(
challenge: try await fetchChallenge(),
name: userInfo.user,
userID: userInfo.accountID)
do {
let passkey = try await authorizationController.performRequest(request)
// Save new passkey to the backend
} catch { … }
}
使用 automatic passkey upgrades 后,只需将 requestStyle 设为 .conditional(02:18):
// Automatic passkey upgrade
func signIn() async throws {
let userInfo = try await signInWithPassword()
guard !userInfo.hasPasskey else { return }
let provider = ASAuthorizationPlatformPublicKeyCredentialProvider(
relyingPartyIdentifier: "example.com")
let request = provider.createCredentialRegistrationRequest(
challenge: try await fetchChallenge(),
name: userInfo.user,
userID: userInfo.accountID,
requestStyle: .conditional)
do {
let passkey = try await authorizationController.performRequest(request)
// Save new passkey to the backend
} catch { … }
}
关键点:
requestStyle: .conditional将请求从弹窗式创建改为条件式自动创建- 如果系统条件不满足,会返回错误,此时可以选择显示原有的 upsell 对话框或下次再试
- 整个过程不会阻塞用户的正常 App 使用流程
Web 实现
标准的 Web passkey 注册是模态弹窗(03:15):
// Modal passkey creation
const options = {
"publicKey": {
"rp": { … },
"user": {
"name": userInfo.user,
…
},
"challenge": …,
"pubKeyCredParams": [ … ]
},
};
await navigator.credentials.create(options);
添加 mediation: "conditional" 参数后即可实现自动升级(04:03):
// Automatic passkey creation
let capabilities = await PublicKeyCredential.getClientCapabilities();
if (!capabilities.conditionalCreate) { return; }
const options = {
"publicKey": {
"rp": { … },
"user": {
"name": userInfo.user,
…
},
"challenge": …,
"pubKeyCredParams": [ … ]
},
"mediation": "conditional"
};
await navigator.credentials.create(options);
关键点:
- 使用
getClientCapabilities()检查浏览器是否支持条件式创建 mediation: "conditional"将请求从用户显式确认改为系统条件判断- 如果不支持,可以回退到传统的模态注册方式
Credential Manager 的新功能
凭证管理器扩展获得了更多能力(09:22):
- 支持 time-based verification codes(基于时间的验证码)
- 可以填充任意文本字段的用户名、密码或一次性代码
- 最多可以选择 3 个 App 用于 AutoFill
在 Info.plist 中声明这些能力(05:04):
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>ASCredentialProviderExtensionCapabilities</key>
<dict>
<key>ProvidesPasswords</key>
<true/>
<key>ProvidesPasskeys</key>
<true/>
<key>SupportsConditionalPasskeyRegistration</key>
<true/>
<key>ProvidesOneTimeCodes</key>
<true/>
<key>ProvidesTextToInsert</key>
<true/>
</dict>
</dict>
</dict>
关键点:
ProvidesPasswords和ProvidesPasskeys声明支持的凭证类型SupportsConditionalPasskeyRegistration表明支持自动 passkey 升级ProvidesOneTimeCodes支持一次性验证码填充ProvidesTextToInsert允许填充任意文本字段
在 Passwords App 中展示
iOS 18 和 macOS Sequoia 引入了新的 Passwords app(10:17)。为了让你的网站和 App 在其中更好地展示:
- 使用 OpenGraph 元数据:Passwords app 会读取
og:site_name来显示网站名称 - 提供高清图标:确保网站有合适的图标文件
- 支持 otpauth:// 链接:让验证码设置成为一键体验
当同一个账号同时有 passkey 和密码时,Passwords app 会将它们合并为单个条目(11:34),用户可以在一个地方看到所有登录方式。
核心启发
1. 为现有账号启用自动 passkey 升级
- 为什么值得做:让用户无需改变任何习惯,就能在登录后自动获得更安全、更快捷的登录方式。Apple 的系统级判断确保只在合适时机创建 passkey,避免打扰。
- 怎么开始:在 iOS/macOS 上将
requestStyle设为.conditional,在 Web 上设置mediation: "conditional"。在 error 回调中保留原有的 upsell 逻辑作为 fallback。
2. 新项目直接使用 passkey 作为唯一登录方式
- 为什么值得做:只有 passkey 的账号不会被钓鱼、不会被遗忘、几乎不需要重置。Session 明确指出这是最终目标——消灭所有可被钓鱼的认证因素。
- 怎么开始:新用户注册时直接创建 passkey,不再提供密码选项。只在确实有兼容性需求时才提供密码作为备选。
3. 优化网站在 Passwords app 中的展示
- 为什么值得做:Passwords app 是 iOS 18/macOS Sequoia 用户的密码管理中心,良好的展示能提升品牌认知度,方便用户识别和管理账号。
- 怎么开始:确保网站所有页面和子域都有正确的 OpenGraph 元数据(
og:site_name),提供高分辨率的图标文件。对于提供验证码的服务,支持otpauth://链接以实现一键设置。
关联 Session
- What’s new in privacy — 隐私功能更新概览,包括权限流程和隐私保护的数据管理方式
- What’s new in location authorization — 定位权限 2.0,介绍新的授权诊断系统 CLServiceSession
- Q&A: Passkeys, iCloud Keychain, and authentication services — 关于 passkeys、认证服务和密码自动填充的文字问答环节
- Deploy passkeys at work — 企业环境下的 passkey 部署与管理方案
评论
GitHub Issues · utterances