What's new in passkeys
Privacy & Security 进阶 0m

Passkeys 新特性

What's new in passkeys

2025年6月9日

在 Apple 官方观看视频

一句话判断

Passkeys 的拼图终于补完了——从注册(Account Creation API)到维护(Signal API 同步凭证变更)到升级(零摩擦自动创建 passkey)到发现(well-known 端点)再到迁移(凭证导入导出),全链路打通。这是对”密码该怎么死”这个问题最完整的回答。

这场 Session 讲了什么

五个独立但互补的更新,覆盖了 passkey 生命周期的每个阶段。

Account Creation API 是注册环节的重做。用户点”用邮箱注册”后,系统弹出一个 Sheet,预填了姓名、邮箱和 passkey 信息,Face ID 一扫就完成注册——不需要填表单、不需要设密码。实现上只需要初始化 ASCredentialProvider、创建 passkey registration request、通过 ASAuthorizationController 执行。三个特有错误需要处理:deviceNotConfiguredForPasskeyCreation(设备未配置 passkey)、canceled(用户关闭 Sheet)、preferSignInWithApple(已有 Apple 登录账户,防止重复注册)。

Signal API 解决的是凭证维护问题。当用户在 App 里改了用户名、吊销了 passkey 或彻底移除了密码,用 ASCredentialUpdater 的 report 方法通知凭证管理器。凭证管理器(比如系统密码 App)会立即更新显示信息。Web 端有对应的 WebAuthn 标准方法。

Automatic Passkey Upgrades 是零摩擦的密码到 passkey 迁移。用户用密码登录后,App 把 registration request 的 style 设成 conditional,系统会在后台静默创建 passkey 并推送通知。没有弹窗、没有中断。如果条件不满足(比如设备不支持),静默失败。

Passkey Management Endpoints 是一个 well-known URL 标准。服务端在 /.well-known/passkey-endpoints 返回 JSON,指定 enroll 和 manage 的 URL。凭证管理器可以读取这个端点,在 App 还用密码登录时就提示”可以升级 passkey”。

Import/Export 是凭证在不同凭证管理器之间迁移的能力。整个过程在 App 之间直传,Face ID 保护,不生成中间文件——比传统的 CSV 导出安全得多。

值得深挖的点

Account Creation API 的 UX 设计值得所有注册流程参考

传统的注册流程是”填表单 -> 验证邮箱 -> 设密码 -> 可能再要求补充信息”,每一步都是流失点。Account Creation API 把所有步骤压缩成一个系统 Sheet:信息预填、密码不需要、Passkey 自动创建。这个 UX 思路不仅适用于 passkey——任何需要快速注册的场景都应该参考”预填 + 集中确认”的模式。

Session 里还强调了一个最佳实践:App 启动时用 preferImmediatelyAvailableCredentials 选项检查是否有已有凭证。用户在 iPad 上第一次打开 App,直接弹出 passkey 登录提示——因为他之前在 iPhone 上注册过,passkey 自动同步了。这种”无感登录”体验是密码永远做不到的。

Signal API 的生态意义

Signal API 看起来只是”通知凭证管理器数据变了”,但它的生态意义更大。之前用户在 App 里改了用户名,凭证管理器里还是旧的——登录时看到的标签和实际不一致,容易搞混。现在通过 reportPublicKeyCredentialUpdate,凭证管理器实时同步。更进一步的 reportUnusedPasswordCredential 告诉凭证管理器”这个账户已经不需要密码了”,凭证管理器可以把密码标记为可删除。

这些信号 API 在 Web 端也有对应实现(signalCurrentUserDetails、signalAllAcceptedCredentials),意味着 App 和网站的凭证管理体验可以保持一致。

Well-known 端点的标准化

/.well-known/passkey-endpoints 是一个跨凭证管理器的标准。不管用户用的是系统密码 App 还是 1Password,都能读取同一个端点来发现你的 passkey 注册页面。这意味着你只需要在服务端实现一次,所有凭证管理器都能获益。响应必须是 200 OK + application/json,不能重定向——这个细节容易踩坑。

代码片段

Account Creation API 核心代码

func signUp() async {
    let provider = ASCredentialIdentityProvider()
    let request = provider.createPasskeyRegistrationRequest(
        acceptedContactIdentifiers: [.email],
        shouldRequestName: true,
        relyingPartyIdentifier: "example.com",
        challenge: fetchChallengeFromServer(),
        userID: generateUserID()
    )

    do {
        let controller = ASAuthorizationController(authorizationRequests: [request])
        let result = try await controller.perform()
        // 获取联系标识、姓名和 passkey
        let contactID = result.contactIdentifier
        let name = result.name
        let passkey = result.passkey
        // 在服务端创建账户
        await createAccount(name: name, email: contactID, passkey: passkey)
    } catch ASCredentialError.preferSignInWithApple {
        // 已有 Apple 登录账户,发起 Sign in with Apple
        try? await signInWithApple()
    } catch {
        // 展示传统注册表单
        showCustomSignUpForm()
    }
}

坑:challenge 必须是服务端生成的一次性值。客户端生成 challenge 会完全破坏安全性。

Automatic Passkey Upgrade

func attemptPasskeyUpgrade(account: Account) async {
    guard !account.hasPasskey else { return }

    let request = ASAuthorizationPlatformPublicKeyCredentialProvider(
        relyingPartyIdentifier: "example.com"
    ).createCredentialRegistrationRequest(
        challenge: fetchChallenge(),
        name: account.username,
        userID: account.userID
    )
    request.style = .conditional  // 关键:静默模式

    do {
        let controller = ASAuthorizationController(authorizationRequests: [request])
        let result = try await controller.perform()
        await savePasskeyOnServer(result.credential)
    } catch {
        // 静默失败,不需要处理
        // 下次密码登录时会再次尝试
    }
}

坑:conditional style 在任何前置条件不满足时都静默失败——包括设备未配置 passcode、用户刚登录时未使用密码、凭证管理器不可用等。不要对这个失败做 UI 提示。

最佳实践

Account Creation API 应该作为新用户注册的首选路径。当它失败(deviceNotConfiguredForPasskeyCreation 或 canceled)时,降级到传统注册表单。不要反过来——先展示表单再建议 passkey,那样会失去速度优势。

Passkey 吊销后,调用 reportAllAcceptedPublicKeyCredentials 传入仍然有效的 credential ID 集合。凭证管理器会删除不在集合里的 passkey。建议每次登录后也周期性调用这个方法做健康检查。

对于还在用密码的已有用户,把 automatic upgrade 设成每次密码登录都尝试。条件不满足就静默跳过,没有任何成本。一旦成功,用户下次登录就能用 passkey,体验质的飞跃。

还有什么值得关注

  • 2025 年 FIDO Alliance 的调查显示 69% 的受访者至少有一个 passkey,Google 数据显示 passkey 登录成功率是密码的 4 倍,TikTok 观察到 97% 的 passkey 登录成功率。
  • passkey 的用户名标签是纯本地数据,不会在认证时发给服务端——用户可以随便改不影响功能。
  • UIRequiresFullscreen Info.plist key 已废弃,下一个 major 版本会忽略——和 passkey 无关但值得注意。
  • 凭证迁移使用 FIDO Alliance 协作制定的数据 schema,覆盖 passkey、密码、验证码等多种凭证类型。
隐私与安全