iOS實現蘋果第三方登錄功能 - Sign in with apple

閑話少說,直接上碼

一. 開啟Sign in with Apple 功能

1. app bundle id 開啟Sign in with Apple

登陸developer賬號,在app bundle ID的Capabilities里,打勾Sign In with Apple.

打勾Sign in with Apple

2. Xcode里開啟Sign in with Apple

打開Xcode 11.0 Beta或更新版本,在項目設置 -> Signing & Capabilities 里,開啟Sign in with Apple選項。

在Xcode中開啟Sign in with Apple

二. 實現

實現概括

實現分四大部分:

  1. 創建Sign in with Apple Button.
  2. 跟用戶提出授權請求.
  3. 根據用戶的授權來驗證用戶.
  4. 處理用戶授權變更.

1. 創建Sign in with Apple Button

import UIKit
import AuthenticationServices

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    
        let button = ASAuthorizationAppleIDButton()
        button.addTarget(self, action: #selector(handleAuthorization), for: .touchUpInside)
        // `handleAuthorization`的實現參閱:2. 跟用戶提出授權請求.
        // 創建好button后,可以安裝需求安裝到所需的位置, 比如 self.view.addSubview(button)
    }
}

2. 跟用戶提出授權請求.

  • handleAuthorization里主要是跟用戶提出用蘋果登陸請求,并要求用戶提供用戶名和email.
  • 發出請求需要創建ASAuthorizationController, 但是需要提供delegatepresentationContextProvider.
    • ASAuthorizationControllerDelegate會提供請求后的結果回調,比如用戶請求失敗,或者用戶請求成功。
    • presentationContextProvider是為驗證的用戶界面提供所需的window.
@objc private func handleAuthorization() {
    if #available(iOS 13.0, *) {
        let requestID = ASAuthorizationAppleIDProvider().createRequest()
        // 這里請求了用戶的姓名和email
        requestID.requestedScopes = [.fullName, .email]
        
        let controller = ASAuthorizationController(authorizationRequests: [requestID])
        controller.delegate = self
        controller.presentationContextProvider = self
        controller.performRequests()
    } else {
        // iOS13以前的版本不支持, 用戶界面可以提示
    }
}

@available(iOS 13.0, *)
extension ViewController: ASAuthorizationControllerDelegate
{
    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        // 請求完成,但是有錯誤
    }
    
    func authorizationController(controller: ASAuthorizationController,
                                 didCompleteWithAuthorization authorization: ASAuthorization)
    {
        // 請求完成, 用戶通過驗證
        if let credential = authorization.credential as? ASAuthorizationAppleIDCredential
        {
            // 拿到用戶的驗證信息,這里可以跟自己服務器所存儲的信息進行校驗,比如用戶名是否存在等。
            let detailVC = DetailVC(cred: credential)
            self.present(detailVC, animated: true, completion: nil)
        }
    }
}

@available(iOS 13.0, *)
extension ViewController: ASAuthorizationControllerPresentationContextProviding
{
    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
        return (UIApplication.shared.delegate as! AppDelegate).window!
    }
}

3. 根據用戶的授權來驗證用戶.

if let credential = authorization.credential as? ASAuthorizationAppleIDCredential

在上面ASAuthorizationControllerDelegate的用戶通過驗證的回調里,可以拿到credential,這里面有一些信息值得提下:

  • 用戶emai: credential.email
  • 用戶名信息:credential.fullName
  • 蘋果提供的用戶ID:credential.user
  • 驗證信息狀態:credential.state
  • refresh token: let code = credential.authorizationCode, let codeStr = String(data: code, encoding: .utf8)
  • access token: let idToken = credential.identityToken, let tokeStr = String(data: idToken, encoding: .utf8)

4. 處理用戶授權/用戶信息變更.

授權或者用戶信息是有可能被改變的,我們能做到就是盡早的檢測出這樣的改變,并做以應對。
檢測授權的狀態需要記錄在上面所得到的

“蘋果提供的用戶ID:credential.user

AppleDelegate里,把之前存的用戶ID放到ASAuthorizationAppleIDProvider里驗證即可,可以得到幾種用戶授權狀態:

  • authorized: 授權合格/合法
  • revoked:授權被撤銷,用戶可以在iOS系統設置了手動撤銷授權。
  • notFound:授權未找到
class AppDelegate: UIResponder, UIApplicationDelegate
{
    var window: UIWindow?
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        if let userID = Keychain.getSavedUserID() {
            let appleIDProvider = ASAuthorizationAppleIDProvider()
            appleIDProvider.getCredentialState(forUserID: "") { (state, error) in
                switch state
                {
                    case .authorized: // 處理合法的授權
                    break
                    case .revoked: // 處理被撤銷的授權
                    break
                    case .notFound: //處理沒有找到的授權
                    break
                    default: // 其他
                    break
                }
            }
        }
        return true
    }
}

如果有錯誤歡迎指出,也歡迎各種討論,謝??!

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 本文主要內容轉載自此處 本文將《指南》和《協議》的更新版本和舊版本進行了一番對比分析,請收閱。 近日蘋果對《蘋果開...
    IBegins閱讀 5,359評論 0 1
  • 累了就要休息,不能苦熬了自己,一年熬到頭,就是春節有幾天空閑,該睡睡,該吃吃,不能再累著自己,身體也需要修復期的。...
    塵_9075閱讀 143評論 0 0
  • 朝牧南山牛,暮聽泉溪流。 午時蟬聲唱,夜半鷓鴣愁。 或問何以知,久聞遂音熟。 漸會境中意,聲聲催快鋤。 戮力禾苗希...
    葉落歲暮閱讀 384評論 4 11
  • 接連出了兩次廢品,我真是個笨蛋! 我已經不喜歡現在的工作了,年前也和老板提出不想做了,可是很多人勸我再干一段時間,...
    我比楊花更飄蕩閱讀 511評論 1 5