iOS 17.0,使用 Apple 登录,错误域=AKAuthenticationError Code=-7091“(null)”和错误 1000

问题描述 投票:0回答:1

在我的应用程序中,我使用 Apple 登录,效果很好。 检查清单:

  • 使用为调试和发布添加的 Apple 功能登录。
  • 请注意,其中一些也针对 CloudKit 配置。

登录效果很好。

但是,在重新启动时,当我想检查登录状态时,我执行此代码

    private func checkLoginStatus() {
        Task {
            do {
                let appleIDProvider = ASAuthorizationAppleIDProvider()
                let credentialState = try await appleIDProvider.credentialState(forUserID: KeychainItem.currentUserIdentifier)
                if credentialState == .authorized {
                    withAnimation {
                        self.isLoggedIn = true
                    }
                }
            } catch {
                fatalError(error.localizedDescription)
            }
        }
    }

此代码总是抛出:

线程 5:致命错误:操作无法完成。 (com.apple.AuthenticationServices.AuthorizationError 错误 1000。)

然而,在此之前不久,我得到:

凭证状态请求返回错误:错误域=AKAuthenticationError Code=-7091“(null)”

该解决方案主要复制自 Apple 的 Juice Sample App。 我不知道这里出了什么问题。任何帮助将不胜感激。

ios swift icloud cloudkit
1个回答
0
投票

我犯了一个愚蠢的错误,没有检查 Juice 示例项目中 Keychain 项的实现。

如果有人遇到此示例项目的问题,我建议在钥匙串项中寻找答案。

这是一个非常简单的会话管理器实现:


import AuthenticationServices

class SessionManager {
    static let shared = SessionManager()
    
    private init() {
//        deleteKeychainItem(service: "your.bundle", account: "appleIDToken") // If your data is corrupted
    }
    
    func saveToKeychain(appleIDCredential: ASAuthorizationAppleIDCredential) {
        do {
            let encodedCredential = try NSKeyedArchiver.archivedData(withRootObject: appleIDCredential, requiringSecureCoding: true)

            let keychainQuery: [String: Any] = [
                kSecClass as String: kSecClassGenericPassword,
                kSecAttrService as String: "your.bundle",
                kSecAttrAccount as String: "appleIDToken",
                kSecValueData as String: encodedCredential,
                kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked
            ]

            let status = SecItemAdd(keychainQuery as CFDictionary, nil)
            if status == errSecSuccess {
                print("Token stored in Keychain successfully")
            } else if status == errSecDuplicateItem {
                print("Token already exists in Keychain")
            } else {
                print("Error storing token in Keychain with status: \(status)")
                // Handle the error appropriately
            }
        } catch {
            print("Error encoding credential: \(error)")
        }
    }

        
    func retrieveFromKeychain() -> ASAuthorizationAppleIDCredential? {
        let keychainQuery: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrService as String: "your.bundle",
            kSecAttrAccount as String: "appleIDToken",
            kSecReturnData as String: true,
            kSecMatchLimit as String: kSecMatchLimitOne
        ]

        var result: AnyObject?
        let status = SecItemCopyMatching(keychainQuery as CFDictionary, &result)

        if status == errSecSuccess, let tokenData = result as? Data {
            do {
                if let credential = try NSKeyedUnarchiver.unarchivedObject(ofClass: ASAuthorizationAppleIDCredential.self, from: tokenData) {
                    return credential
                } else {
                    print("Credential could not be unarchived")
                }
            } catch {
                print("Error decoding credential: \(error)")
            }
        } else if status == errSecItemNotFound {
            print("Token not found in Keychain")
        } else {
            print("Error retrieving token from Keychain with status: \(status)")
        }
        return nil
    }

    func deleteKeychainItem(service: String, account: String) {
        let keychainQuery: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrService as String: service,
            kSecAttrAccount as String: account,
        ]
        
        let status = SecItemDelete(keychainQuery as CFDictionary)
        if status == errSecSuccess {
            print("Keychain item deleted successfully")
        } else if status == errSecItemNotFound {
            print("Keychain item not found")
        } else {
            print("Error deleting Keychain item with status: \(status)")
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.