Apple login

目前Apple login 在App Store审核时并不是强制集成的,但是只要App 集成任何一个其他的第三方认证登录(微信、Google等)就必须也得集成Apple login,这是Apple 的强制要求,否则审核时App 会被拒绝。 Apple Login 官方文档

Apple login 是iOS 13 后才支持的API也就是说iOS 13 以前的系统是不能集成Apple login的,下面具体介绍一下集成Apple login 需要做哪几方面的工作。

准备工作

  • Xcode 需要升级到 11 以上的版本
  • iOS 13 以上系统的测试设备
  • 开发者需要到Apple 开发者账号下勾选上Sign In with Apple 登录选项,重新下载Profile文件。
    image.png

    1.登录Apple开发者账号
    2.选择左边Identifier 栏目,在右侧选择要开通Sign In with Apple的Identifiers 点击打开,下拉找到Sign In with Apple勾选上。
    3.点击右上角save保存会出现Modify App Capabilities弹窗,点击Confirm。
    开启后 profile 将失效需要重新编辑 profile 文件
    4.在xcode项目中开启sign in with apple
    image.png

App 端开发工作

添加依赖库

image.png

创建Apple Login Button

Apple 提供了官方的Sign In with Apple button,当然这个按钮也可以自定义,自定义按钮规则
代码

let authorizationButton = ASAuthorizationAppleIDButton()
        authorizationButton.addTarget(self, action: #selector(handleAuthorizationAppleIDButtonPress), for: .touchUpInside)
        if #available(iOS 13.0, *) {
            self.loginProviderStackView.addArrangedSubview(authorizationButton)
        }

Button 的type有登录类型ASAuthorizationAppleIDButtonTypeSignIn和注册类型ASAuthorizationAppleIDButtonTypeSignUp(只能在13.2+有效,13.0-13.2需要自定义)。
Button的style的有几种类型,但都是黑白配。

向Apple 发起请求

苹果还把 iCloud KeyChain password 集成到了这套 API 里,我们在使用的时候,只需要在创建 request 的时候,多创建一个 ASAuthorizationPasswordRequest,这样如果 KeyChain 里面也有登录信息的话,可以直接使用里面保存的用户名和密码进行登录。

 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()
    }

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
            let authorizationCode = appleIDCredential.authorizationCode
            UIPasteboard.general.string = String.init(data: authorizationCode!, encoding: String.Encoding.utf8)
            
            // 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
        }
    }

基本流程:向Apple 发送认证请求,请求返回结果后,用结果信息中authorizationCode向App的服务端接口发送用户认证请求进行用户登录验证。初次登录时可以让用户编辑显示的用户名及是否隐藏邮箱,第二次登录之后用户进行认证即可。苹果官方开发文档 苹果官方完成demo
注意:获取的用户信息中:email、NSPersonNameComponents对象所有属性是只有第一次请求的时候才会返回,之后就算 停止使用 Apple ID 再重新授权都不会返回用户信息。
authorizeCredential.user 是用户的唯一ID,同一个开发者账号下这个ID一致。
authorizeCredential.authorizationCode验证码,每次返回的不一样,看服务端使用那种验证方式而定是否使用。
authorizeCredential.identityToken用户的验证token,有一定的有效期,到期后会刷新。
Apple建议将用户ID保存在钥匙串中以便在App启动的时候进行检查AppleID的登录状态。
用户注销 AppleId 或 停止使用 Apple ID 的状态处理

服务端验证

服务端验证分两种验证方式:一种是验证码验证、一种是JWT验证。具体详见Apple 官方文档:https://developer.apple.com/documentation/signinwithapplerestapi

手机端需要提交 user 、authorizationCode 、 identityToken 字段信息(code和token字段苹果返回的是 base64 Data 形式,手机端可以先转换 base64 字符串之后在给服务器)到服务器。然后服务器通过 https://appleid.apple.com/auth/token 该接口,并拼接对应参数去验证,接口相关信息苹果有提供。
后端接口需要的参数

  • Client_id:App 的BundleID
  • client_secret:后台生成的JWT key。
  • Code:客户端传过的authorizationCode
  • grant_type:常量authorizationCode

参数的获取方法:
登录Apple开发者账号-menbership 获取teamid ;
创建private_key:进入证书栏certificates、IDs&Profiles,选择keys标签(如果没有keys标签,可能是您登录的Apple开发者账号不是超管账号,没有权限。)-现在添加--给key命名并选择对应的bundleid。
注:该private_key只能下载一次。
根据Apple返回的结果中sub字段即是用户的ID,可以和手机端的user字段对比验证。

client_secret 的生成

打开终端cd ‘文件路径’, touch secret_gen.rb 这个命令执行完成后就可以看到这个文件,打开文件把下面的代码粘贴进去配置相应的信息,继续终端步骤 ruby secret_gen.rb

require "jwt"

key_file = "Path to the private key"
team_id = "Your Team ID"
client_id = "Your App Bundle ID"
key_id = "The Key ID of the private key"
validity_period = 180 # In days. Max 180 (6 months) according to Apple docs.

private_key = OpenSSL::PKey::EC.new IO.read key_file

token = JWT.encode(
{
iss: team_id,
iat: Time.now.to_i,
exp: Time.now.to_i + 86400 * validity_period,
aud: "[https://appleid.apple.com](https://links.jianshu.com/go?to=https%3A%2F%2Fappleid.apple.com)",
sub: client_id
},
private_key,
"ES256",
header_fields=
{
kid: key_id
}
)
puts token

你可能感兴趣的:(Apple login)