iosswiftfirebasesign-in-with-apple

Cause of error setting up Sign in with Apple for Firebase in Swift on iOS 13?


I have been following https://firebase.google.com/docs/auth/ios/apple and it does mention the error I am receiving re "sending the SHA256-hashed nonce as a hex string" but it doesn't offer any help to solve it and my searches haven't given me a solution which works.

My view controller code extract is


        fileprivate var currentNonce: String?

        @objc @available(iOS 13, *)
        func startSignInWithAppleFlow() {
          let nonce = randomNonceString()
          currentNonce = nonce
          let appleIDProvider = ASAuthorizationAppleIDProvider()
          let request = appleIDProvider.createRequest()
          request.requestedScopes = [.fullName, .email]
          request.nonce = sha256(nonce)
            print(request.nonce)

          let authorizationController = ASAuthorizationController(authorizationRequests: [request])
          authorizationController.delegate = self
          authorizationController.presentationContextProvider = self
          authorizationController.performRequests()
        }
        @available(iOS 13, *)
        private 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()
            print(hashString)
          return hashString
        }
    }
    @available(iOS 13.0, *)
    extension LoginViewController: ASAuthorizationControllerDelegate {

      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 {
            print("Unable to fetch identity token")
            return
          }
          guard let idTokenString = String(data: appleIDToken, encoding: .utf8) else {
            print("Unable to serialize token string from data: \(appleIDToken.debugDescription)")
            return
          }
          // Initialize a Firebase credential.
            print(nonce)
            let credential = OAuthProvider.credential(withProviderID: "apple.com",
                                                      idToken: idTokenString,
                                                      accessToken: nonce)

            print(credential)
          // Sign in with Firebase.
          Auth.auth().signInAndRetrieveData(with: credential) { (authResult, error) in
            if (error != nil) {
              // Error. If error.code == .MissingOrInvalidNonce, make sure
              // you're sending the SHA256-hashed nonce as a hex string with
              // your request to Apple.
                print(authResult)
                print(error!)
                print(error!.localizedDescription)
              return
            }
            // User is signed in to Firebase with Apple.
            // ...
          }
        }
      }

This section is different from the instructions on the webpage as Xcode gave an error


    let credential = OAuthProvider.credential(withProviderID: "apple.com",
                                                      idToken: idTokenString,
                                                      accessToken: nonce)

If I print the nonce immediately before


    let credential = OAuthProvider.credential(withProviderID: "apple.com",
                                                      idToken: idTokenString,
                                                      accessToken: nonce)

I get 2eNjrtagc024_pd3wfnt_PZ0N89GZ_b6_QJ3IZ_

response.nonce value is cd402f047012a2d5c129382c56ef121b53a679c0a5c5e37433bcde2967225afe

Obviously these aren't the same but I can't seem to work out what I am doing wrong.

Full error output is

Error Domain=FIRAuthErrorDomain Code=17999 "An internal error has occurred, print and inspect the error details for more information." UserInfo={NSUnderlyingError=0x60000388a820 {Error Domain=FIRAuthInternalErrorDomain Code=3 "(null)" UserInfo={FIRAuthErrorUserInfoDeserializedResponseKey={
    code = 400;
    errors =     (
                {
            domain = global;
            message = "MISSING_OR_INVALID_NONCE : Nonce is missing in the request.";
            reason = invalid;
        }
    );
    message = "MISSING_OR_INVALID_NONCE : Nonce is missing in the request.";
}}}, FIRAuthErrorUserInfoNameKey=ERROR_INTERNAL_ERROR, error_name=ERROR_INTERNAL_ERROR, NSLocalizedDescription=An internal error has occurred, print and inspect the error details for more information.}
An internal error has occurred, print and inspect the error details for more information.

Solution

  • I ran into the same error.

    Solution: Just run

    pod update

    Explanation:

    The problem is as @ethanrj says. The documentation says to do

    let credential = OAuthProvider.credential( 
        withProviderID: "apple.com", IDToken: appleIdToken, rawNonce: rawNonce )
    

    but this gives an error and Xcode will suggest the following (rawNonce -> accessToken):

    let credential = OAuthProvider.credential( 
        withProviderID: "apple.com", IDToken: appleIdToken, accessToken: rawNonce )
    

    This is because pod install will install FirebaseAuth 6.12 by default, when you really need 6.13 since the new function signature is only available there. You can view the source here.