[SOLVED] Firebase Overwrites Signin with Google Account

Issue

This Content is from Stack Overflow. Question asked by Maicol Llano Moncada

As we have seen in another posts related to this situation and github issues, the expected behavior is that Google IDP overrides other non trusted providers related to the same email as an example, another account with the same email + password (non-verified).

Trying to understand Firebase Authentication one account per email address and trusted providers

Firebase Overwrites Signin with Google Account

https://github.com/firebase/firebase-ios-sdk/issues/5344

https://groups.google.com/g/firebase-talk/c/ms_NVQem_Cw/m/8g7BFk1IAAAJ

So, ok, according to google that’s the expected behavior.

Our questions comes when we go to the documentation and there’s an example of a user login in with google and getting this error auth/account-exists-with-different-credential just because there’s another account created with email+password with the same email. Then, they recommend to catch the error, check the user email related login methods and ask the user to login with the other provider and then link to google.

Does this make sense ? If they say the expected behavior is that google as a trusted provider will override the others (this is what happens to us) how is possible that the case of the code example would even occur ?

https://firebase.google.com/docs/auth/web/google-signin#expandable-1

FirebaseAuth auth = FirebaseAuth.instance;

// Create a credential from a Google Sign-in Request
var googleAuthCredential = GoogleAuthProvider.credential(accessToken: 'xxxx');

try {
  // Attempt to sign in the user in with Google
  await auth.signInWithCredential(googleAuthCredential);
} on FirebaseAuthException catch (e) {
  if (e.code == 'account-exists-with-different-credential') {
    // The account already exists with a different credential
    String email = e.email;
    AuthCredential pendingCredential = e.credential;

    // Fetch a list of what sign-in methods exist for the conflicting user
    List<String> userSignInMethods = await auth.fetchSignInMethodsForEmail(email);

    // If the user has several sign-in methods,
    // the first method in the list will be the "recommended" method to use.
    if (userSignInMethods.first == 'password') {
      // Prompt the user to enter their password
      String password = '...';

      // Sign the user in to their account with the password
      UserCredential userCredential = await auth.signInWithEmailAndPassword(
        email: email,
        password: password,
      );

      // Link the pending credential with the existing account
      await userCredential.user.linkWithCredential(pendingCredential);

      // Success! Go back to your application flow
      return goToApplication();
    }

    // Since other providers are now external, you must now sign the user in with another
    // auth provider, such as Facebook.
    if (userSignInMethods.first == 'facebook.com') {
      // Create a new Facebook credential
      String accessToken = await triggerFacebookAuthentication();
      var facebookAuthCredential = FacebookAuthProvider.credential(accessToken);

      // Sign the user in with the credential
      UserCredential userCredential = await auth.signInWithCredential(facebookAuthCredential);

      // Link the pending credential with the existing account
      await userCredential.user.linkWithCredential(pendingCredential);

      // Success! Go back to your application flow
      return goToApplication();
    }

    // Handle other OAuth providers...
  }
} 

There’s another example with the same structure in the flutter docs:

https://firebase.google.com/docs/auth/flutter/errors#handling_account-exists-with-different-credential_errors



Solution

As the documentation says: certain email domains have a trusted provider. Most prominently: Google is the trusted provider for @gmail.com addresses, since it’s the only issuer of these email addresses.

If a user first registers their gmail address with say Facebook, and later there is a registration with that same gmail address from the Google provider, the latter registration is considered to overrule the former. If the user later signs in with Facebook again, the two accounts can be linked.

As far as I know, the only way to prevent this is to allow multiple accounts per email address.

Also see these posts by some of the Firebase Authentication engineers:


This Question was asked in StackOverflow by Aubtin Samai and Answered by Frank van Puffelen It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?