Firebase Apple登录无用户新增及代码适配问题求助
Apple登录Firebase无用户新增+方法参数报错排查
问题概述
按Firebase官方指南配置SignInWithApple按钮后,点击按钮Firebase控制台未新增用户;同时指南中的OAuthProvider.appleCredential方法在Xcode中提示无该参数,只能改用OAuthProvider.credential方法,怀疑此改动导致问题,附上代码请求排查:
官方指南中无法使用的代码
// Initialize a Firebase credential, including the user's full name. let credential = OAuthProvider.appleCredential(withIDToken: idTokenString, rawNonce: nonce, fullName: appleIDCredential.fullName) // Sign in with Firebase.
实际使用的登录按钮代码
//Mark:apple sign in button SignInWithAppleButton(onRequest: { request in request.requestedScopes = [.fullName, .email] let nonce = fireAuth.randomNonceString() fireAuth.currentNonce = nonce request.nonce = fireAuth.sha256(nonce) }, onCompletion: { result in if case.failure(let failure) = result { errorMessage = failure.localizedDescription } else if case.success(let success) = result { if let appleIDCredential = success.credential as? ASAuthorizationAppleIDCredential { guard let nonce = fireAuth.currentNonce else { fatalError("Invalid state: a login callback was received, but no login request was sent.") } guard let appleIDToken = appleIDCredential.identityToken else { print("Unable to fetch identity token.") return } guard let idTokenString = String(data: appleIDToken, encoding: .utf8) else { print("Unable to serialise token string from data: \(appleIDToken.debugDescription)") return } // Initialize a Firebase credential let credential = OAuthProvider.credential(withProviderID:"apple.com", idToken: idTokenString, rawNonce: nonce) // Sign in with Firebase. Auth.auth().signIn(with: credential){(authResult,err) in if let error = err{ print(error.localizedDescription) return } } //User successfully logged into firebase... print("Logged In Success") } } }) .frame(width:150,height:40)
FireAuth工具类代码
class FireAuth: ObservableObject { // static let share = FireAuth() @State var currentNonce: String? = String() init() {} // Apple Sign In func randomNonceString(length: Int = 32) -> String { precondition(length > 0) var randomBytes = [UInt8](repeating: 0, count: length) let errorCode = SecRandomCopyBytes(kSecRandomDefault, randomBytes.count, &randomBytes) if errorCode != errSecSuccess { fatalError( "Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)" ) } let charset: [Character] = Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._") let nonce = randomBytes.map { byte in // Pick a random character from the set, wrapping around if needed. charset[Int(byte) % charset.count] } return String(nonce) } //Hashing function using CryptoKit func sha256(_ input: String) -> String { let inputData = Data(input.utf8) let hashedData = SHA256.hash(data: inputData) let hashString = hashedData.compactMap { String(format: "%02x", $0) }.joined() return hashString } }
核心问题排查与修复
1. OAuthProvider.appleCredential方法不存在的原因
该方法是Firebase Auth SDK旧版本API,新版本已统一使用OAuthProvider.credential(withProviderID:idToken:rawNonce:),你的替换是正确的,此改动不是用户未新增的直接原因。
2. 用户未新增的关键问题
(1)currentNonce属性修饰符错误
@State仅适用于SwiftUI视图结构体,在ObservableObject类中需使用@Published,否则nonce无法正确传递,导致Firebase验证失败:
// 错误写法 @State var currentNonce: String? = String() // 正确写法 @Published var currentNonce: String?
(2)异步登录逻辑错误
你在Auth.auth().signIn(with:credential)的闭包外部打印"Logged In Success",但Firebase登录是异步操作,只有闭包执行完成才代表登录成功,当前写法会导致即使登录失败也会打印成功,无法准确判断状态:
// 错误写法 Auth.auth().signIn(with: credential){(authResult,err) in if let error = err{ print(error.localizedDescription) return } } print("Logged In Success") // 正确写法 Auth.auth().signIn(with: credential){(authResult,err) in if let error = err{ print(error.localizedDescription) return } // 登录成功后才执行后续逻辑 print("Logged In Success") if let user = authResult?.user { print("用户UID:\(user.uid)") } }
(3)额外验证点
- 确认Firebase控制台已开启Apple登录,Team ID、Bundle ID、签名证书配置完全正确;
- 使用真实设备测试(模拟器可能存在Apple登录权限问题);
- 检查
signIn闭包中的authResult是否返回用户信息,确认验证流程是否完成; - 打印
request.nonce和sha256(nonce)的结果,确保两者一致(Firebase要求nonce哈希值为SHA-256小写十六进制字符串)。
3. 修正后的关键代码片段
FireAuth类修正
class FireAuth: ObservableObject { static let shared = FireAuth() // 改为单例,方便全局调用 @Published var currentNonce: String? init() {} func randomNonceString(length: Int = 32) -> String { precondition(length > 0) var randomBytes = [UInt8](repeating: 0, count: length) let errorCode = SecRandomCopyBytes(kSecRandomDefault, randomBytes.count, &randomBytes) if errorCode != errSecSuccess { fatalError("Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)") } let charset: [Character] = Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._") let nonce = randomBytes.map { charset[Int(byte) % charset.count] } return String(nonce) } func sha256(_ input: String) -> String { let inputData = Data(input.utf8) let hashedData = SHA256.hash(data: inputData) return hashedData.compactMap { String(format: "%02x", $0) }.joined() } }
登录按钮闭包修正
SignInWithAppleButton(onRequest: { request in request.requestedScopes = [.fullName, .email] let nonce = FireAuth.shared.randomNonceString() FireAuth.shared.currentNonce = nonce request.nonce = FireAuth.shared.sha256(nonce) }, onCompletion: { result in switch result { case .failure(let failure): print(failure.localizedDescription) case .success(let success): guard let appleIDCredential = success.credential as? ASAuthorizationAppleIDCredential else { print("无效的凭证类型") return } guard let nonce = FireAuth.shared.currentNonce else { fatalError("无效状态:未找到nonce") } guard let appleIDToken = appleIDCredential.identityToken else { print("无法获取身份令牌") return } guard let idTokenString = String(data: appleIDToken, encoding: .utf8) else { print("无法序列化令牌字符串") return } let credential = OAuthProvider.credential(withProviderID:"apple.com", idToken: idTokenString, rawNonce: nonce) Auth.auth().signIn(with: credential) { authResult, error in if let error = error { print("Firebase登录错误:\(error.localizedDescription)") return } // 登录成功处理 if let user = authResult?.user { print("登录用户UID:\(user.uid)") print("用户邮箱:\(user.email ?? "未获取到邮箱")") // 此处可添加UI跳转或用户信息同步逻辑 } } } }) .frame(width:150,height:40)
内容的提问来源于stack exchange,提问作者Tracy9988 Xu
相关产品推荐
相关产品推荐

