Firebase Authentication Link Facebook to Google

Viewed 106

After many tests I decided to create a new xCode project to better understand Firebase authentication with multiple providers.

I set up in Firebase -> SignIn Methods -> An account per email address

An account per email address

Prevents users from creating multiple accounts using the same email address with different authentication providers

At this point I have implemented, carefully following the Firebase guide, the login with Facebook and with Google .. Everything seems to work perfectly but I always find myself with the same error that I can't manage:

When my user creates a Firebase account via Google he is no longer able to log in if he decides to use Facebook.

Facebook returns its error when it completes its authentication flow with Firebase:

Firebase Error With Facebook Provider: An account already exists with the same email address but different sign-in credentials. Sign in using a provider associated with this email address.

Continuing to follow the documentation step by step I stopped here (firebase explains how to handle this error)

I have also implemented error handling but after calling Auth.auth().fetchSignInMethods Firebase says I should authenticate the user with the existing provider, at this point how do I get the credentials for authentication with the existing provider?


  • I wouldn't want to reopen the existing provider controller to get new credentials

  • Am I obliged to ask the user to log in with the existing provider and show another access controller again (in this case that of Google)?

  • How should I handle this situation?


 override func viewDidLoad() {
    super.viewDidLoad()
    facebookSetup()
 }
    
 func facebookSetup() {
    let loginButton = FBLoginButton(permissions: [ .publicProfile, .email ])
    loginButton.center = view.center
    loginButton.delegate = self
    view.addSubview(loginButton)
 }

 //MARK: - FACEBOOK Delegate
 func loginButton(_ loginButton: FBLoginButton, didCompleteWith result: LoginManagerLoginResult?, error: Error?) {
        
    if let error = error {
       print(error.localizedDescription)
       return
    }
       
    let credential = FacebookAuthProvider.credential(withAccessToken: AccessToken.current!.tokenString)

    Auth.auth().signIn(with: credential) { (authResult, error) in
       
        if let error = error {
           print("\n FIREBASE: ",error.localizedDescription)
                
           // An account with the same email already exists.
           if (error as NSError?)?.code == AuthErrorCode.accountExistsWithDifferentCredential.rawValue {

               // Get pending credential and email of existing account.
               let existingAcctEmail = (error as NSError).userInfo[AuthErrorUserInfoEmailKey] as! String
               let pendingCred = (error as NSError).userInfo[AuthErrorUserInfoUpdatedCredentialKey] as! AuthCredential

                // Lookup existing account identifier by the email.
                Auth.auth().fetchSignInMethods(forEmail: existingAcctEmail) { providers, error in
                        
                     if (providers?.contains(GoogleAuthProviderID))! {
                            
                          // Sign in with existing account.
                          Auth.auth().signIn(with: "? ? ? ?") { user, error in
                          // Successfully signed in.
                          if user != nil {

                             // Link pending credential to account.
                             Auth.auth().currentUser?.link(with: pendingCred) { result, error in
                                
                                // Link Facebook to Google Account
                             }
                         }
                     }
                 }
             }
         }
     }
 }
0 Answers
Related