Enhance your Sign in with Apple experience
System & Services 进阶 20m

增强你的 Sign in with Apple 体验

Enhance your Sign in with Apple experience

2022年6月6日

在 Apple 官方观看视频

一句话判断

iOS 16 让你的 App 启动时就能自动展示已有登录凭据——密码、Sign in with Apple、Passkey 全部一次搞定,彻底告别”选错登录方式创建重复账号”的噩梦。

这场 Session 讲了什么

Sign in with Apple 的核心问题之一是账号重复:用户可能先用邮箱密码注册,后来又用 Sign in with Apple 创建了第二个账号。Session 的前半部分专门解决这个痛点。

iOS 16 新增了 preferImmediatelyAvailableCredentials 选项。在 App 启动时,你可以同时查询密码凭据和 Sign in with Apple 凭据。如果用户有现成的登录方式,系统直接展示选择界面——用户选对了就不会创建重复账号。

Session 的后半部分深入讲解了 Apple ID Credential 的每个字段含义和使用场景。User ID 是跨 App Team 的稳定标识符。fullName 和 email 只在首次创建账号时返回,后续登录不会再提供——你必须安全缓存这些值。realUserStatus 是基于设备端机器学习的反欺诈指标。

值得深挖的点

  • 启动时凭据发现:在 ASAuthorizationController 中同时包含 ASAuthorizationAppleIDProviderASAuthorizationPasswordProvider,调用 performRequests(with: .preferImmediatelyAvailableCredentials)。如果没有现成凭据,API 不会强制展示 Sign in with Apple 界面——返回错误让你走标准登录流程。
  • Credential 变化监听:用户可能撤销 Sign in with Apple 授权、删除账号或切换 Apple ID。通过 ASAuthorizationAppleIDProvider.credentialState(forUserID:) 定期检查授权状态。
  • realUserStatus 的三档策略:“likelyReal” 跳过额外验证(不显示 CAPTCHA),“unknown” 当作有限信息的新账号处理(不要封堵),“unsupported” 说明系统无法判断。
  • 账号删除处理:如果你的 App 支持账号删除,必须通过 Sign in with Apple REST API 通知 Apple 撤销用户的 Token。

代码片段

import AuthenticationServices

// App 启动时自动发现已有凭据
func discoverExistingCredentials() {
    let appleIDProvider = ASAuthorizationAppleIDProvider()
    let passwordProvider = ASAuthorizationPasswordProvider()

    let controller = ASAuthorizationController(
        authorizationProviders: [appleIDProvider, passwordProvider]
    )
    controller.delegate = self
    controller.presentationContextProvider = self

    // iOS 16 新选项:只请求立即可用的凭据
    controller.performRequests(
        options: .preferImmediatelyAvailableCredentials
    )
}

func authorizationController(
    controller: ASAuthorizationController,
    didCompleteWithAuthorization authorization: ASAuthorization
) {
    switch authorization.credential {
    case let appleIDCredential as ASAuthorizationAppleIDCredential:
        // 用户选择了 Sign in with Apple
        let userID = appleIDCredential.user
        let fullName = appleIDCredential.fullName
        let email = appleIDCredential.email

    case let passwordCredential as ASPasswordCredential:
        // 用户选择了密码登录
        let username = passwordCredential.user
        let password = passwordCredential.password

    default:
        break
    }
}

func authorizationController(
    controller: ASAuthorizationController,
    didCompleteWithError error: Error
) {
    // 没有现成凭据 → 展示标准登录界面
    showStandardLoginFlow()
}

最佳实践

  • 在 App 启动时调用凭据发现,让用户一键登录
  • 首次获取的 fullName 和 email 必须安全缓存,后续登录不再提供
  • 提供 Account Authentication Modification Extension 让用户升级密码账号到 Sign in with Apple
  • 定期检查 credential state,处理授权撤销的情况
  • realUserStatus 为 “likelyReal” 时可以跳过 CAPTCHA 等额外验证

还有什么值得关注

  • “Meet passkeys” 介绍了基于 FIDO 的无密码登录方案
  • “Discover Sign in with Apple at Work & School” 覆盖了 Managed Apple ID 的支持
  • Account Authentication Modification Extension 让密码→Sign in with Apple 的升级变得无缝
  • 同时支持密码和 Sign in with Apple 的 App 应该优先展示已有凭据
WWDC 2022