目前Apple login 在App Store審核時并不是強制集成的,但是只要App 集成任何一個其他的第三方認(rèn)證登錄(微信、Google等)就必須也得集成Apple login,這是Apple 的強制要求,否則審核時App 會被拒絕。 Apple Login 官方文檔
Apple login 是iOS 13 后才支持的API也就是說iOS 13 以前的系統(tǒng)是不能集成Apple login的,下面具體介紹一下集成Apple login 需要做哪幾方面的工作。
準(zhǔn)備工作
- Xcode 需要升級到 11 以上的版本
- iOS 13 以上系統(tǒng)的測試設(shè)備
- 開發(fā)者需要到Apple 開發(fā)者賬號下勾選上Sign In with Apple 登錄選項,重新下載Profile文件。
image.png
1.登錄Apple開發(fā)者賬號
2.選擇左邊Identifier 欄目,在右側(cè)選擇要開通Sign In with Apple的Identifiers 點擊打開,下拉找到Sign In with Apple勾選上。
3.點擊右上角save保存會出現(xiàn)Modify App Capabilities彈窗,點擊Confirm。
開啟后 profile 將失效需要重新編輯 profile 文件
4.在xcode項目中開啟sign in with apple
image.png
App 端開發(fā)工作
添加依賴庫
創(chuàng)建Apple Login Button
Apple 提供了官方的Sign In with Apple button,當(dāng)然這個按鈕也可以自定義,自定義按鈕規(guī)則
代碼
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 發(fā)起請求
蘋果還把 iCloud KeyChain password 集成到了這套 API 里,我們在使用的時候,只需要在創(chuàng)建 request 的時候,多創(chuàng)建一個 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 發(fā)送認(rèn)證請求,請求返回結(jié)果后,用結(jié)果信息中authorizationCode向App的服務(wù)端接口發(fā)送用戶認(rèn)證請求進行用戶登錄驗證。初次登錄時可以讓用戶編輯顯示的用戶名及是否隱藏郵箱,第二次登錄之后用戶進行認(rèn)證即可。蘋果官方開發(fā)文檔 蘋果官方完成demo
注意:獲取的用戶信息中:email、NSPersonNameComponents對象所有屬性是只有第一次請求的時候才會返回,之后就算 停止使用 Apple ID 再重新授權(quán)都不會返回用戶信息。
authorizeCredential.user 是用戶的唯一ID,同一個開發(fā)者賬號下這個ID一致。
authorizeCredential.authorizationCode驗證碼,每次返回的不一樣,看服務(wù)端使用那種驗證方式而定是否使用。
authorizeCredential.identityToken用戶的驗證token,有一定的有效期,到期后會刷新。
Apple建議將用戶ID保存在鑰匙串中以便在App啟動的時候進行檢查AppleID的登錄狀態(tài)。
用戶注銷 AppleId 或 停止使用 Apple ID 的狀態(tài)處理
服務(wù)端驗證
服務(wù)端驗證分兩種驗證方式:一種是驗證碼驗證、一種是JWT驗證。具體詳見Apple 官方文檔:https://developer.apple.com/documentation/signinwithapplerestapi
手機端需要提交 user 、authorizationCode 、 identityToken 字段信息(code和token字段蘋果返回的是 base64 Data 形式,手機端可以先轉(zhuǎn)換 base64 字符串之后在給服務(wù)器)到服務(wù)器。然后服務(wù)器通過 https://appleid.apple.com/auth/token 該接口,并拼接對應(yīng)參數(shù)去驗證,接口相關(guān)信息蘋果有提供。
后端接口需要的參數(shù)
- Client_id:App 的BundleID
- client_secret:后臺生成的JWT key。
- Code:客戶端傳過的authorizationCode
- grant_type:常量authorizationCode
參數(shù)的獲取方法:
登錄Apple開發(fā)者賬號-menbership 獲取teamid ;
創(chuàng)建private_key:進入證書欄certificates、IDs&Profiles,選擇keys標(biāo)簽(如果沒有keys標(biāo)簽,可能是您登錄的Apple開發(fā)者賬號不是超管賬號,沒有權(quán)限。)-現(xiàn)在添加--給key命名并選擇對應(yīng)的bundleid。
注:該private_key只能下載一次。
根據(jù)Apple返回的結(jié)果中sub字段即是用戶的ID,可以和手機端的user字段對比驗證。
client_secret 的生成
打開終端cd ‘文件路徑’, touch secret_gen.rb 這個命令執(zhí)行完成后就可以看到這個文件,打開文件把下面的代碼粘貼進去配置相應(yīng)的信息,繼續(xù)終端步驟 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