使用Firebase Auth

时间:2019-12-18 16:15:07

标签: swift facebook firebase google-cloud-platform firebase-authentication

当具有相同电子邮件地址的帐户已存在时,尝试使用FB登录凭据登录Firebase身份验证帐户时遇到困难。最终,我想将两个身份验证提供程序链接到同一个Firebase用户帐户,但是目前我无法获得FB凭据(如果已经存在)使用以下代码登录Firebase(如果已经存在),我认为该代码完全遵循Firebase文档。我已经限制了单个用户(电子邮件)具有基于Auth Provider的多个帐户的功能。当我删除“原始” Firebase用户帐户时,Facebook登录名能够按预期的方式登录并创建用户帐户,因此,仅当已经有来自其他身份验证提供商的具有相同电子邮件地址的Firebase身份验证帐户时,问题才会出现。 >

场景

在我测试的场景中,我已经创建了一个电子邮件/密码帐户(原始),并试图通过FB登录(使用与电子邮件/密码帐户相同的电子邮件地址)添加我的FB帐户。原始帐户。我可以获取FB AccessToken和FB凭据,但是当我将其传递给Auth.auth()。sign(with:credential .....时,它总是会出错,并出现以下错误:

错误

错误域= FIRAuthErrorDomain代码= 17012“帐户已经存在,具有相同的电子邮件地址,但登录凭据不同。请使用与此电子邮件地址关联的提供商进行登录。 UserInfo = {FIRAuthErrorUserInfoNameKey = ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL,FIRAuthErrorUserInfoEmailKey=akash11x@gmail.com,FIRAuthErrorUserInfoUpdatedCredentialKey =,NSLocalizedDescription =已存在具有相同电子邮件地址但登录凭据不同的帐户。使用与此电子邮件地址关联的提供商登录。

代码

@IBAction func fbLoginButton(_ sender: FBButton) {

    let loginManager = LoginManager()
    loginManager.logIn(permissions: ["public_profile", "email"], from: self) { (result, error) in
        if error != nil {
            return
        }

        print(result)
        guard let accessToken = AccessToken.current else {
            print("Failed to get access token")
            return
        }
        print(accessToken)

        let credential = FacebookAuthProvider.credential(withAccessToken: accessToken.tokenString)
        print(credential)

        Auth.auth().signIn(with: credential, completion: { (firebaseUser, error) in //Can't get passed this point when another account with the same email address already exists
            if error != nil {
                print("Could not login into Firebase using FB credentials")
                return
            }

            print("This is the FirebaseUser after FB Login: \(firebaseUser)")

            firebaseUser?.user.link(with: credential, completion: { (authResult, error) in
                if error != nil {
                    print("Firebase Auth Providers not linked")
                    return
                }

                //                let prevUser = Auth.auth().currentUser
                //                Auth.auth().signIn(with: credential) { (authResult, error) in
                //                  if let error = error {
                //                    // ...
                //                    return
                //                  }
                //                  // User is signed in
                //                  // ...
                //                }
                //                            // Merge prevUser and currentUser accounts and data
                //
                // ...

                //This user has a profile, go to tab controller
                let tabBarVC = self.storyboard?.instantiateViewController(withIdentifier: Constants.Storyboard.tabBarController)

                self.view.window?.rootViewController = tabBarVC
                self.view.window?.makeKeyAndVisible()

            })
        })
    }
}

1 个答案:

答案 0 :(得分:0)

万一其他人遇到同样的问题。

通过使用登录流程,使新的身份验证提供程序具有与现有Firebase身份验证帐户相同的电子邮件地址,似乎无法“实时”链接Firebase身份验证提供程序。因此,我的解决方案是在他们使用电子邮件/密码登录后在个人资料中创建“将Facebook链接到您的个人资料”按钮。然后,该按钮在Firebase中创建链接,以将facebook识别为该帐户的辅助身份验证提供程序。为了进行测试,我注销并使用了“使用Facebook登录”按钮,所有操作均按预期进行。

我认为此UX大大降低了该功能的实用性,但经过数周的研究,我能得出最好的结果。

个人资料上的代码以将Facebook链接到电子邮件/密码原始帐户

    @IBAction func fbLoginButton(_ sender: FBButton) {

    let loginManager = LoginManager()
    loginManager.logIn(permissions: ["public_profile", "email"], from: self) { (result, error) in
        if error != nil {
            return
        }

        print(result)

        guard let accessToken = AccessToken.current else {
            print("Failed to get access token")
            return
        }
        print(accessToken)

        let credential = FacebookAuthProvider.credential(withAccessToken: accessToken.tokenString)
        print(credential)

        if let user = Auth.auth().currentUser {
            print("This is the user:  \(user)")
            // [START link_credential]
            user.link(with: credential) { _, error in
                // [START_EXCLUDE]
                if let error = error {
                    print("FB did not link to account.  \(error)")
                    return
                }
            }
        }
    }
}

登录页面上的代码(如下),电子邮件/密码登录

别忘了将LoginButtonDelegate添加到视图控制器

@IBAction func fbLoginButton(_ sender: FBButton) {

    let loginManager = LoginManager()
    loginManager.logIn(permissions: ["public_profile", "email"], from: self) { (result, error) in
        if error != nil {
            return
        }

        guard let accessToken = AccessToken.current else {
            print("Failed to get access token")
            return
        }

        let credential = FacebookAuthProvider.credential(withAccessToken: accessToken.tokenString)

        Auth.auth().signIn(with: credential) { (authResult, error) in

            if let error = error {
                // ...
                return
            }

            let user = authResult?.user

            //Check if user is nill
            if user != nil {

                //This means that we have a user, now check if they have a User document
                UserService.getUserProfile() { (u) in

                    if u == nil {

                        //No profile, go to Profile Controller
                        self.performSegue(withIdentifier: Constants.Segue.profileViewController, sender: self)
                    }
                    else {

                        //Save the logged in user to local storage
                        LocalStorageService.saveCurrentUser(user: u!)

                        //This user has a profile, go to tab controller
                        let tabBarVC = self.storyboard?.instantiateViewController(withIdentifier: Constants.Storyboard.tabBarController)

                        self.view.window?.rootViewController = tabBarVC
                        self.view.window?.makeKeyAndVisible()

                    }

                }

            }

        }

    }
}

对于按钮本身,我在视图中使用情节提要添加了一个按钮,并使用了客户类“ FBSDKButton”并相应地设置了样式:

    let fbButtonText = NSAttributedString(string: "Link facebook to Profile")
    fbLoginButton.setAttributedTitle(fbButtonText, for: .normal)

    let fbButtonText = NSAttributedString(string: "Login with facebook")
    fbLoginButton.setAttributedTitle(fbButtonText, for: .normal)

最后,请确保您导入了适当的库;我用了:     导入FirebaseAuth     导入FBSDKCoreKit     导入FacebookCore     导入Facebook登录     导入FBSDKLoginKit     导入Firebase