在 iOS 13 上的 Swift 中使用 Apple for Firebase 设置登录时出错的原因是啥?

Posted

技术标签:

【中文标题】在 iOS 13 上的 Swift 中使用 Apple for Firebase 设置登录时出错的原因是啥?【英文标题】:Cause of error setting up Sign in with Apple for Firebase in Swift on iOS 13?在 iOS 13 上的 Swift 中使用 Apple for Firebase 设置登录时出错的原因是什么? 【发布时间】:2020-03-19 12:48:29 【问题描述】:

我一直在关注https://firebase.google.com/docs/auth/ios/apple,它确实提到了我收到的错误“将 SHA256 哈希随机数作为十六进制字符串发送”,但它没有提供任何帮助来解决它,而且我的搜索没有给出我有一个可行的解决方案。

我的视图控制器代码提取是


        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.
            // ...
          
        
      

此部分与网页上的说明不同,因为 Xcode 出错了


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

如果我在之前打印随机数


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

我得到 2eNjrtagc024_pd3wfnt_PZ0N89GZ_b6_QJ3IZ_

response.nonce 值为 cd402f047012a2d5c129382c56ef121b53a679c0a5c5e37433bcde2967225afe

显然这些不一样,但我似乎无法弄清楚我做错了什么。

完整的错误输出是

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.

【问题讨论】:

【参考方案1】:

我遇到了同样的错误。

解决方案: 跑吧

pod update

解释:

问题正如@ethanrj 所说。文档说要做

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

但这会产生错误,Xcode 会提示以下内容(rawNonce -> accessToken):

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

这是因为pod install 将默认安装 FirebaseAuth 6.12,当您真正需要 6.13 时,因为新功能签名仅在那里可用。可以查看源码here。

【讨论】:

非常感谢,解决了,我自己也应该想到的!最终结果 let credential = OAuthProvider.credential(withProviderID: "apple.com", idToken: idTokenString, rawNonce: nonce, accessToken: nil)【参考方案2】:

您是否可能使用了错误的凭据方法?在documentation 上,看起来采用随机数的是:

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

但是你在这里使用的那个需要一个访问令牌,不确定这是否有帮助。

【讨论】:

谢谢,但我试过了,Xcode 给出了一个红色错误并说将 rawNonce 更改为 idToken,我还检查了 pod 文件,并且在任何项目文件中从未提及 rawNonce,格式最接近的方法是我正在使用的一个。

以上是关于在 iOS 13 上的 Swift 中使用 Apple for Firebase 设置登录时出错的原因是啥?的主要内容,如果未能解决你的问题,请参考以下文章

iOS App 在 iOS 13 上的编译器生成代码中崩溃

sceneDidEnterBackground 上的 URL 请求(iOS13)

如何在 Swift 5 和 iOS 13 中使用 CIFilter sunbeamsGenerator?

Firebase Twitter oAuth 回调不适用于 Swift ios13

socket.io-client-swift 包解析在 Xcode13 Beta 项目中失败

Swift:在 IOS13+ 上设置状态栏颜色(使用 statusBarManager)