SynthReel/SynthReel/Libs/SRLogin/SRLogin+apple.swift
2025-12-02 13:27:27 +08:00

117 lines
4.0 KiB
Swift

//
// SRLogin+third.swift
// SynthReel
//
// Created by CSGY on 2025/12/1.
// Copyright © 2025 SR. All rights reserved.
//
import UIKit
import AuthenticationServices
extension SRLogin {
private struct AssociatedKeys {
static var appleLoginHandle: Int?
}
private var appleLoginHandle: ((_ model: SRThirdModel?) -> Void)? {
set {
objc_setAssociatedObject(self, &AssociatedKeys.appleLoginHandle, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
}
get {
return objc_getAssociatedObject(self, &AssociatedKeys.appleLoginHandle) as? ((_ model: SRThirdModel?) -> Void)
}
}
func appleLogin(completer: ((_ model: SRThirdModel?) -> Void)?) {
self.appleLoginHandle = completer
let appleIDProvider = ASAuthorizationAppleIDProvider()
let request = appleIDProvider.createRequest()
request.requestedScopes = [.fullName, .email]
let authorizationController = ASAuthorizationController(authorizationRequests: [request])
authorizationController.delegate = self
authorizationController.presentationContextProvider = self
authorizationController.performRequests()
}
private func jwtDecode(jwtStr: String) -> [String: Any]? {
let segments = jwtStr.components(separatedBy: ".")
guard segments.count > 1 else { return nil }
var base64String = segments[1]
// Base64
let requiredLength = 4 * Int(ceil(Double(base64String.count) / 4.0))
let paddingLength = requiredLength - base64String.count
if paddingLength > 0 {
base64String += String(repeating: "=", count: paddingLength)
}
// URL
base64String = base64String.replacingOccurrences(of: "-", with: "+")
base64String = base64String.replacingOccurrences(of: "_", with: "/")
// Base64
guard let data = Data(base64Encoded: base64String),
let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []),
let payload = jsonObject as? [String: Any] else {
return nil
}
return payload
}
}
//MARK: ASAuthorizationControllerDelegate
extension SRLogin: ASAuthorizationControllerDelegate {
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
let userIdentifier = appleIDCredential.user
let fullName = appleIDCredential.fullName
let email = appleIDCredential.email
let identityToken = appleIDCredential.identityToken.flatMap { String(data: $0, encoding: .utf8) }
let identityTokenParams = self.jwtDecode(jwtStr: identityToken ?? "")
var model = SRThirdModel()
model.platform = .apple
model.third_id = userIdentifier
model.giving_name = fullName?.givenName
model.family_name = fullName?.familyName
model.avator = identityTokenParams?["picture"] as? String
model.email = identityTokenParams?["email"] as? String
debugLog(userIdentifier)
debugLog(fullName)
debugLog(email)
appleLoginHandle?(model)
appleLoginHandle = nil
}
}
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
appleLoginHandle?(nil)
appleLoginHandle = nil
}
}
//MARK: ASAuthorizationControllerPresentationContextProviding
extension SRLogin: ASAuthorizationControllerPresentationContextProviding {
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
return SRTool.keyWindow!
}
}