I'm getting a final error when trying to sign-in to my app. I asked a similar question here. Not sure what's happening, but an invalid login callback occurs after I authenticate.
I'm trying to sign-in with Apple using Firebase. The docs were updated just a month ago.
Here's my code:
import SwiftUI
import LocalAuthentication
import FirebaseAuth
import CryptoKit
import _AuthenticationServices_SwiftUI
final class SignInManager: ObservableObject {
@Published var errorMessage = ""
private var currentNonce: String?
// Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce
private func randomNonceString(length: Int = 32) -> String {
precondition(length > 0)
let charset: [Character] =
Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._")
var result = ""
var remainingLength = length
while remainingLength > 0 {
let randoms: [UInt8] = (0 ..< 16).map { _ in
var random: UInt8 = 0
let errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random)
if errorCode != errSecSuccess {
fatalError(
"Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)"
)
}
return random
}
randoms.forEach { random in
if remainingLength == 0 {
return
}
if random < charset.count {
result.append(charset[Int(random)])
remainingLength -= 1
}
}
}
return result
}
@available(iOS 13, *)
private 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
}
}
extension SignInManager {
func handleSignInWithAppleRequest(_ request: ASAuthorizationAppleIDRequest) {
request.requestedScopes = [.fullName, .email]
let nonce = randomNonceString()
currentNonce = nonce
request.nonce = sha256(nonce)
}
func handleSignInWithAppleCompletion(_ result: Result<ASAuthorization, Error>) {
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 = 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 fetdch identify token.")
return
}
guard let idTokenString = String(data: appleIDToken, encoding: .utf8) else {
print("Unable to serialize token string from data: \(appleIDToken.debugDescription)")
return
}
let credential = OAuthProvider.credential(withProviderID: "apple.com",
idToken: idTokenString,
rawNonce: nonce)
Task {
do {
let result = try await Auth.auth().signIn(with: credential)
await updateDisplayName(for: result.user, with: appleIDCredential)
}
catch {
print("Error authenticating: \(error.localizedDescription)")
}
}
}
}
}
}
I thought it had something to do with the OAuth credential, but this seems configured correctly.
The .success case in handleSignInWithAppleCompletion succeeds, but afterwards immediately crashes the app.
Help.
When I print my .success case and when I print my currentNonce
