iosswiftfirebase

Replace 'IDToken' with 'idToken' Swift Sign in with Apple using Firebase


I am trying to use Sign In with Apple using Firebase. The Firebase Docs say to use let credential = OAuthProvider.credential(withProviderID: "apple.com", IDToken: idTokenString, rawNonce: nonce), however Xcode gives and error and suggests a fix.

enter image description here

If I follow Xcode's suggestion, the app crashes with Invalid state: A login callback was received, but no login request was sent.. I have already seen all the other questions regarding this on Stack Overflow, but none of them resolve the issue. Is this an issue with the current version of the Firebase SDK or an error on my part.


Solution

  • Try my code, It works for me

    import CryptoKit
    import Firebase
    import AuthenticationServices
    
    extension SocietyLoginViewController {
    
        @available(iOS 13, *)
        func appleLogin() {
            let nonce = randomNonceString()
            currentNonce = nonce
            let appleIDProvider = ASAuthorizationAppleIDProvider()
            let request = appleIDProvider.createRequest()
            request.requestedScopes = [.fullName, .email]
            request.nonce = sha256(nonce)
            let authorizationController = ASAuthorizationController(authorizationRequests: [request])
            authorizationController.delegate = self
            authorizationController.presentationContextProvider = self
            authorizationController.performRequests()
        }
    
        @available(iOS 13, *)
        func sha256(_ input: String) -> String {
            let inputData = Data(input.utf8)
            let hashedData = SHA256.hash(data: inputData)
            let hashString = hashedData.compactMap {
                return String(format: "%02x", $0)
            }.joined()
    
            return hashString
        }
    
        // Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce
        func randomNonceString(length: Int = 32) -> String {
            precondition(length > 0)
            let charset: Array<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.0, *)
    extension SocietyLoginViewController: ASAuthorizationControllerDelegate , ASAuthorizationControllerPresentationContextProviding {
    
        func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
            return self.view.window!
        }
    
        func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
            if let appleIDCredential = authorization.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 {
                    return
                }
                guard let idTokenString = String(data: appleIDToken, encoding: .utf8) else {
                    return
                }
                // Initialize a Firebase credential.
                let credential = OAuthProvider.credential(withProviderID: "apple.com", idToken: idTokenString, rawNonce: nonce)
                // Sign in with Firebase.
    
            }
        }
    
        func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
            // Handle error.
            print("Sign in with Apple errored: \(error)")
       }
    }