iOS - Sign in with Apple
2020-08-10 本文已影响0人
ienos
2019.09.12 苹果发布了一条新的审核规则,要求使用了第三方登陆的 App 需要集成 Sign in with Apple.
[官方文档]
基本条件
- Framework — — Authentication Services
- iOS 13.0 +
- Xcode 11.3 +
集成步骤
- Xcode, 在 Capaility 中添加 Sign in with Apple
- 代码集成
Swift 代码
1. Add a Sign in with Apple Button
func setupProviderLoginView() {
let authorizationButton = ASAuthorizationAppleIDButton()
authorizationButton.addTarget(self, action: #selector(handleAuthorizationAppleIDButtonPress), for: .touchUpInside)
self.loginProviderStackView.addArrangedSubview(authorizationButton)
}
Apple Button
2. Requset Authorization with Apple ID
- 根据 requestedScopes 获取授权范围,
.full
和.email
,获取用户全名
和email
- 系统将会检查用户是否已经在他们的设备上登陆了 Apple ID。如果用户没有登录,App 将推出一个窗口引导用户到设置页面中登陆 Apple ID
@objc
func handleAuthorizationAppleIDButtonPress() {
let appleIDProvider = ASAuthorizationAppleIDProvider()
let request = appleIDProvider.createRequest()
request.requestedScopes = [.fullName, .email]
let authorizationController = ASAuthorizationController(authorizationRequests: [request])
authorizationController.delegate = self
authorizationController.presentationContextProvider = self
authorizationController.performRequests()
}
Authorization
- 用户名:用户可以编辑账户信息,用户可以编辑他们的姓和名字
- 邮箱:选择其他 email 作为他们的联系信息,和隐藏他们的 email 在 app 中;如果用户选择隐藏 email 地址,Apple 生成一个代理 email 地址去转发用户的私有 email 地址
- return window 用于模式推出登陆 Apple 的内容
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
return self.view.window!
}
3. Handle User Credentials
用户授权结果,代理方法会检查该 Credential 是 ASAuthorizationAppleIDCredential
还是 ASPasswordCredential
- Successful Handler
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
switch authorization.credential {
case let appleIDCredential as ASAuthorizationAppleIDCredential:
// Create an account in your system.
let userIdentifier = appleIDCredential.user
let fullName = appleIDCredential.fullName
let email = appleIDCredential.email
// For the purpose of this demo app, store the `userIdentifier` in the keychain.
self.saveUserInKeychain(userIdentifier)
// For the purpose of this demo app, show the Apple ID credential information in the `ResultViewController`.
self.showResultViewController(userIdentifier: userIdentifier, fullName: fullName, email: email)
case let passwordCredential as ASPasswordCredential:
// Sign in using an existing iCloud Keychain credential.
let username = passwordCredential.user
let password = passwordCredential.password
// For the purpose of this demo app, show the password credential as an alert.
DispatchQueue.main.async {
self.showPasswordCredentialAlert(username: username, password: password)
}
default:
break
}
}
建议在自己的账号系统下面加上 useridentifier
- Failed Handler
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
// Handle error.
}
4. Request Existing Credentials
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 (ASAuthorizationAppleIDCredential)和 iCloud keychain password(ASPasswordCredential),这个操作和 Request Authorization with Apple ID 类似,这个方法调用之后会回
authorizationController(controller:didCompleteWithAuthorization:)
5. Check User Credentials at Launch
检查 App 是否已 AppleID 登陆授权
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let appleIDProvider = ASAuthorizationAppleIDProvider()
appleIDProvider.getCredentialState(forUserID: KeychainItem.currentUserIdentifier) { (credentialState, error) in
switch credentialState {
case .authorized:
break // The Apple ID credential is valid.
case .revoked, .notFound:
// The Apple ID credential is either revoked or was not found, so show the sign-in UI.
DispatchQueue.main.async {
self.window?.rootViewController?.showLoginViewController()
}
default:
break
}
}
return true
}
6. ASAuthorizationError Code
- Cancel — — 1001
- Unknown — — 1000
- Failed — — 1004
- NotHandled — — 1003
- InvalidResponse — — 1002
注意事项
- 基于目前的调查,Sign in with Apple 能够获取授权信息有: email、fullName(包括 First Name 和 Last Name)。在第一次授权登陆 App 中(之后 Apple ID 会保存该 App 已授权),必须确保用户被正确创建(如果云端创建失败,需要保存在本地);因为除了第一次外,之后再次登陆除了返回 userIdentifier 之外,不会返回用户的任何信息。
在测试阶段,我们可以手动删除 Apple ID 和 App 的授权绑定(iPhone Setting -> Apple ID -> Password & Security -> Apple ID logins -> {YOUR APP} -> Stop using Apple ID)