Authentication
iOS13中 authentication 的更新主要有:
- sign in with Apple
- password-based authentication
- warning for weak passwords
- OAuth sign-in
- USB security keys on macOS
主要还是围绕 Sign in 展开:
- 使用 Apple ID sign in
- sign in 的时候利用已登陆的账号自动输入账号密码
- 密码太弱时的提醒
这些内容都围绕着: 安全-方便-友好 而展开的,接下来重点谈谈 sign in with Apple。
Sign in with Apple
文档中,Apple提到:
Apple does not use Sign In with Apple to profile users or their activity in apps.
对注重个人隐私的用户,这是一个非常值得期待的功能。
准备工作
在Xcode11中,开启sign in 功能,本质上是在 entitlement 文件中添加了一个key:”com.apple.developer.applesignin”,它的值是字符串数组。然后在设备上确认账号,该账号必须是开启过两步验证的Apple ID。确认后,该账号就是 primary App ID
。接下来,使用该 primary App ID创建私钥,并记录下该 key id。
如果有多个App的,可以创建 app group,共享 Apple ID。
实现
集成过程可以简单地分为:
- 添加内置(built-in)按钮
- 发起authentication请求
- 响应协议并和自己的后台通信(如果需要的话)
添加按钮:
func setUpProviderLoginView() {
let button = ASAuthorizationAppleIDButton()
button.addTarget(self, action: #selector(handleAuthorizationAppleIDButtonPress),for: .touchUpInside)
self.loginProviderStackView.addArrangedSubview(button)
}
发起请求:
@objc func handleAuthorizationButtonPress() {
let request = ASAuthorizationAppleIDProvider().createRequest()
request.requestedScopes = [.fullName, .email]
let pwdRequest = ASAuthorizationPasswordProvider().createRequest()
let controller = ASAuthorizationController(authorizationRequests: [request, pwdRequest])
controller.delegate = self
controller.presentationContextProvider = self
controller.performRequests()
这里,发起请求的时候,通常也希望使用密码自动填充功能,所以使用了 ASAuthorizationPasswordProvider 创建请求。
响应协议:
func authorizationController(controller _: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
switch authorization.credential {
case let credential as ASAuthorizationAppleIDCredential:
let userIdentifier = credential.user
let identityToken = credential.identityToken
let authCode = credential.authorizationCode
let realUserStatus = credential.realUserStatus
// Sign the user in using the Apple ID credential
// Create account in your system
case let credential as ASPasswordCredential:
// Sign the user in using their existing password credential
default: break
}
}
func authorizationController(_: ASAuthorizationController, didCompleteWithError error: Error) {
// Handle error
}
处理登录状态的变化
这里有两种场景:
- 使用App的时候,不再使用Apple ID (stop using Apple ID with app)
- 在设备上退出登录(sign out of the device)
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
}
}
因为sign in with Apple本质是 OAuth,因此存在authentication 重置(revoke)的情形。这种情况下,可以:
// 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 后,如果要给用户发送信息,那么需要使用 Apple’s private email relay service
。首要的,在开发者账户中配置:
Certificates, Identifiers&Profiles->More->Configure Sign In with Apple
将相关内容注册后即可,注意添加的域名需要添加 SPF DNS TXT 记录,这样才能允许苹果代替你的域名发送邮件。
这些也可以在Xcode中添加App的capability。
参考 references
Configuration
Sign in with Apple
HumanGuideline: Sign in with Apple
Comments