Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FirebaseAuthInvalidCredentialsException when using "One account per email address"

... if you don't allow multiple accounts with the same email address, a user cannot create a new account that signs in using a Google Account with the email address [email protected] if there already is an account that signs in using the email address [email protected] and a password.

I was able to sign in with Google provider for the same email that was already registered via Email provider, so Google provider replaced Email provider and latter then fails to sign in with FirebaseAuthInvalidCredentialsException: The password is invalid or the user does not have a password..

Steps to reproduce:

Sign up with Email provider -> Sign out -> Sign in with Google provider -> Sign out

Basically it should not allow to replace one provider with another and throw FirebaseAuthUserCollisionException: The email address is already in use by another account.

Some code that I use for sign in/sign out:

  public void signUpEmail(String email, String password) {
    mFirebaseAuth.createUserWithEmailAndPassword(email, password)
        .addOnCompleteListener(this, task -> {
          if (!task.isSuccessful()) {
            Log.e("signUpWithEmail", task.getException());
          }
        });
  }

  private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
    AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
    mFirebaseAuth.signInWithCredential(credential)
        .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
          @Override public void onComplete(@NonNull Task<AuthResult> task) {
          if (!task.isSuccessful()) {
            Log.e("signInWithCredential", task.getException());
          }
        }
    });
  }

  public void signInEmail(String email, String password) {
    mFirebaseAuth.signInWithEmailAndPassword(email, password)
        .addOnCompleteListener(this, task -> {
          if (!task.isSuccessful()) {
            Log.e("signInWithEmail", task.getException());
          }
      });
  }

  public void signOut() {
    Auth.GoogleSignInApi.signOut(mGoogleApiClient);
    mFirebaseAuth.signOut();
    startSignInActivity();
  }

Thank you!

like image 520
Ivan V Avatar asked Jun 03 '16 17:06

Ivan V


2 Answers

To optimize the login UI steps and enhance account security, Firebase Authentication has a concept of 'trusted provider', where the identity provider is also the email service provider. For example, Google is the trusted provider for @gmail.com addresses, Yahoo is the trusted provider for @yahoo.com addresses, and Microsoft for @outlook.com addresses.

In the "One Account per Email address" mode, Firebase Authentication tries to link account based on email address. If a user logins from trusted provider, the user immediately signs into the account since we know the user owns the email address.

If there is an existing account with the same email address but created with other credentials (e.g. password or non-trusted provider), the previous credentials are removed for security reasons.

A phisher (who is not the email address owner) might create the initial account - removing the initial credential would prevent the phisher from accessing the account afterwards. The legit user can set up a password by going through the password reset flow, where she would need to prove she owns the email address.

like image 108
Jin Liu Avatar answered Nov 08 '22 01:11

Jin Liu


Multiple accounts per email address will create a new user with a different uid for different providers using the same email.

To recreate:

  1. Sign in with google email x@x
  2. Sign in with facebook email x@x
  3. Create email password account x@x

Now you'll get 3 different users.

If you use the strongly recommended single accounts per email, the 3 providers above would be within the same user (one uid).

When you first create the google account x@x and try to sign in with new facebook account with email x@x, you will get an error that linking is required to proceed. You will then have to sign in the first google user and link the new facebook user to it.

like image 2
bojeil Avatar answered Nov 08 '22 02:11

bojeil