Sign In with Apple 的设计准则和功能实现
在你的 app 或者网站上展示一个「Sign In with Apple」按钮意味着人们可以只通过他们已经拥有的 Apple ID 进行登录或注册,跳过填写个人信息、确认电子邮箱和选择密码的部分。Sign In with Apple 通过给用户一个一致的、他们可以信任的登录体验提供了一个全新的、更加隐私的方式以简化和加快登录 app 和网站的过程,也方便了用户不需要记住多个账户和密码。在你需要请求用户的名字和电子邮箱的地方,用户可以选择对他们的真实电子邮箱进行保密,而提供一个独一无二的、随机的、可收发邮件的电子邮箱地址。
Sign In with Apple 让人们通过 Face ID 或者 Touch ID 完成授权变得简单,并且内建了两步验证以增加安全层级。Apple 不会通过 Sign In with Apple 的活动在 app 中收集用户的个性化资料和他们的具体活动。
Sign In with Apple 提供了反欺骗的特性,它可以通过机器学习和其他信息提供给开发者一个新用户是真实人类还是需要进一步观察的标志。
目录
- 设计帐户注册和登录流程
- Sign In with Apple 按钮
- 实现 Sign In with Apple
设计帐户注册和登录流程
- 让用户登录只为了交互有价值的信息:例如,人们可能需要创建一个账户来让 app 可以提供个性化的体验、在 app 中访问额外的功能或者同步数据,如果你的 app 不需要基于账户的功能,那就不需要让用户登录。
- 在你的所有 app 和网站中考虑使用 Sign In with Apple:为了一个一致性的登录体验,推荐你在你 app 覆盖的所有苹果平台和网站上使用 Sign In with Apple。
- 登录的请求越往后越好:当用户还没做什么有用的事情就被强制登录时,人们可能会放弃使用 app。在向用户发出请求并让用户提供信息前给用户一个熟悉你 app 的机会。例如,一个流媒体播放 app 在需要登录播放内容前可以先让用户看看 app 提供了什么内容。
- 在任何可能的时候,直到用户要做出购买决定时再让用户创建账户:如果你的服务支持访客结算系统,在交易完成之后处理好结算过程,并可以给用户一个快速创建账户的机会。
- 向用户解释清楚登录的好处以及如何注册你的服务:如果你的 app 需要登录账户,那就在登录界面上给用户展示一个清晰友好的说明,描述清楚为什么需要登录以及登录的好处。还有,记住并不是每一个使用你 app 的人在一开始就有一个账户。
- 注册账户时只收集必要的信息:如果只是为了创建一个独一无二的用户标识符,那就不需要收集用户的名字和电子邮箱信息。
Sign In with Apple 按钮
为了帮助人们注册一个账户和登录账户,最好使用 Apple 为 Sign In with Apple 功能提供的熟悉的按钮。当你使用系统 API 创建 Sign In with Apple 按钮时,你可以获得下面这些好处:
- 一个确保使用了 Apple 提供的标题、字体、颜色、样式的按钮;
- 确保了当你改变按钮样式时,按钮的内容可以保持合适的比例;
- 自动翻译按钮上的标题到用户设备设置的语言;
- 为了与你的 UI 样式匹配,对按钮圆角半径的调整的功能支持。
Sign In with Apple 提供了两种按钮样式变种:「Sign In with Apple」 和 「Continue with Apple」。根据需要,选择最适合你的服务的登录场景的那种样式。
对于 Sign In with Apple 按钮有三种外观:白色(White)、带描边的白色(White with Outline Rule)、黑色(Black)。根据你要展示按钮处的 UI 背景选择最适合的外观。
白色
在可以提供足够对比度的深色或者彩色背景上使用白色外观。
带描边的白色
在白色或者不能提供足够对比度的浅色背景上使用带描边的白色外观。不要在黑色或者太饱和颜色的背景上使用。
黑色
在白色或者可以提供足够对比度的浅色背景上使用黑色外观。不要在黑色或者深色的背景上使用。
按钮尺寸和位置
- 让 Sign In with Apple 按钮展示的显眼一些:让 Sign In with Apple 按钮和其他登录按钮具有相同的尺寸,避免人们需要滚动屏幕才能看到按钮的情况。
- 调整圆角半径以与 app 中的其他登录按钮样式相匹配:默认情况下,Sign In with Apple 有一个圆角半径。你可通过改变这个半径值让按钮变成矩形或者药丸形状的按钮。
- 保证最小按钮尺寸和按钮周围的边距:取决于不同的地区,按钮的标题长度可能会发生变化。使用下面推荐的指导值。
实现 Sign In with Apple
纵览
当用户点击 Sign In with Apple 按钮后,用户会看到一个根据你 app 要求提供的信息而填好了信息的表单显示在屏幕上,像是名字和电子邮箱。用户可以在提供原始电子邮箱或者一个新的由 Apple 提供的邮箱之间做出选择。当用户点击继续按钮后,就完成了登录。你的 app 也会获得一个独一无二、固定 ID、用户的名字以及一个可以让用户收到邮件的电子邮件地址,不再需要用户做收取验证邮件、点击验证链接这样的事。
当用户在一台新的设备上登录时,一个轻轻的点击就可以登录之前的用户并开始使用你的 app。
Sign In with Apple 为你的 app 提供了一套流线化的账户设置体验,不需要填写复杂的表格,只需要轻轻一点。用户从 App Store 使用他的 Apple ID 下载了 app,在 app 中也顺其自然地通过 Sign In with Apple 完成登录。开发者也获得了一个已验证并且可以让用户收到邮件的邮箱,即使用户隐藏了自己的真实邮箱,提供的新的邮箱收取的邮件也可以通过 Apple 的转发服务转到用户的真实邮箱,同样用户也可以使用这个新的邮箱进行邮件回复。
Apple 也可以在使用 Sign In with Apple 登录时,通过机器学习和其他获取的信息告诉开发者这个用户是真实的还是未知的。如果是真实的,你就不需要再判断,尽管给这个用户良好的使用体验,如果是未知的,那可能是一个真人用户,也可能是一个机器人。
Sign In with Apple 也是跨平台的,不仅可以在所有苹果平台上使用,也可以通过 JS API 在网站、Windows、Android 上使用。
让 Sign In with Apple 与你的 app 结合
分成下图的四个部分:按钮、授权、鉴权、处理变动。先展示 Sign In with Apple 按钮,接着配置和执行授权的请求,在用户看到 Sign In with Apple 按钮并通过 Face ID/Touch ID 完成确认后,授权的结果会返回给 app。这时你需要与 Apple ID 服务器确认结果并在你的 app 中创建一个新用户。最后,凭据状态可能会发生变化,你的 app 需要处理处理好这些变化状态。
Button 按钮
只需要几行代码,你就可以把 AuthorizationAppleIDButton
添加到你的 app 中。具体代码如下:
// Add “Sign In with Apple” button to your login view func setUpProviderLoginView() { let button = ASAuthorizationAppleIDButton() button.addTarget(self, action: #selector(handleAuthorizationAppleIDButtonPress),for: .touchUpInside) self.loginProviderStackView.addArrangedSubview(button) }
Authorization 授权
利用几行代码,你就可以初始化一个 Apple ID 授权请求。具体的代码如下:
// Configure request, setup delegates and perform authorization request @objc func handleAuthorizationButtonPress() { let request = ASAuthorizationAppleIDProvider().createRequest() request.requestedScopes = [.fullName, .email] let controller = ASAuthorizationController(authorizationRequests: [request]) controller.delegate = self controller.presentationContextProvider = self controller.performRequests() }
Verification 鉴权
在授权后,app 如果鉴权成功会从凭据中获得一系列信息,如果用户中断了过程或者发生了错误需要有错误处理的逻辑。具体的代码如下:
func authorizationController(controller _: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { if let credential = authorization.credential as? ASAuthorizationAppleIDCredential { let userIdentifier = credential.user let identityToken = credential.identityToken let authCode = credential.authorizationCode let realUserStatus = credential.realUserStatus // Create account in your system } } func authorizationController(_: ASAuthorizationController, didCompleteWithError error: Error) { // Handle error }
对于凭据中的信息,userID 是一个独一无二、稳定的、团队范围内的用户识别符,你可以在不同的平台中使用它获取用户信息,它是与你的开发者账户绑定的。鉴权数据包括身份 token 和授权 code,token 的生命周期很短,可以与 Apple ID 服务器交换新的 token。可选的,系统还会返回你请求的账户信息,比如名字和电子邮箱。最后是一个之前提到的真实用户指示标志。
Handling Changes 处理变动
你的用户可能会在你的 app 中停止使用 Apple ID 登录,可能会在设备中登出。授权服务框架提供了一个快速 API 供开发者获取相关状态。具体的代码如下:
let provider = ASAuthorizationAppleIDProvider() provider.getCredentialState(forUserID: "currentUserIdentifier") { (credentialState, error) in switch(credentialState){ case .authorized: // Apple ID Credential is valid case .revoked: // Apple ID Credential revoked, handle unlink case .notFound: // Credential not found, show login UI default: break } }
NotificationCenter 也可以发出通知,告诉 app 用户的凭据状态已经失效。当失效时,在设备上退出登录,进一步可以引导用户重新登录。具体代码如下:
// Register for revocation notification let center = NotificationCenter.default let name = NSNotification.Name.ASAuthorizationAppleIDProviderCredentialRevoked let observer = center.addObserver(forName: name, object: nil, queue: nil) { (Notification) in // Sign the user out, optionally guide them to sign in again }
用户使用 Sign In with Apple 在你的 app 中注册了用户,他可能还会在其他设备上使用你的 app 或者需要重新登录。当第一次进入 app 时,系统会告诉用户曾经使用 Apple ID 注册了用户,经过 Face ID 检查后就可以完成登录。
同时,通过相同的 API,iCloud 钥匙串也可以实现此功能。你需要同时支持这两种登录请求。
当用户已存在时,具体的代码如下:
///Prompts the user if an existing iCloud Keychain credential or Apple ID credential exists. func performExistingAccountSetupFlows() { // Prepare requests for both Apple ID and password providers. let requests = [ASAuthorizationAppleIDProvider().createRequest(), ASAuthorizationPasswordProvider().createRequest()] // Create an authorization controller with the given requests. let authorizationController = ASAuthorizationController(authorizationRequests: requests) authorizationController.delegate = self authorizationController.presentationContextProvider = self authorizationController.performRequests() }
判断是通过 Apple ID 凭据登录还是 iCloud 钥匙串登录的具体代码如下:
func authorizationController(controller _: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { switch authorization.credential { case let credential as ASAuthorizationAppleIDCredential: let userIdentifier = credential.user // Sign the user in using the Apple ID credential case let credential as ASPasswordCredential: // Sign the user in using their existing password credential default: break } }
跨平台
在浏览器中,你也可以通过 JS SDK 实现用户熟悉的登录窗口,通过输入 Apple ID 和密码完成登录。其 API 与原生的相似。
特别的,在 Safari 浏览器上,点击网页上的 Sign In with Apple 按钮会直接定向到一个原生的像 Apple Pay 一样的表单,用户可以通过 Touch ID 授权快速完成登录。
Best Practices