23

Within the Firebase console I have specifically set it to only allow "One account per email address". This is found on the sign-in method tab under "advanced".

I have an account created using the Google login method that has an address like "me@gmail.com". If I then choose to sign-in via Facebook using an account that also uses "me@gmail.com", Firebase is allowing it with the exception that the email address in the Users entity is null.

The Firebase documentation states:

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 ex@gmail.com if there already is an account that signs in using the email address ex@gmail.com and a password.

Does this only count if you are trying to create a Firebase login directly with a username/password vs creating an account from two providers like Facebook and Google? I would be under the impression that if it finds a duplicate email address it should reject the registration/login. I do realize the quote states "and a password" which makes me wonder.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
C6Silver
  • 3,127
  • 2
  • 21
  • 49
  • could you provide the source for your quote. i dont find documentation in firebase about this yet online. do you have a link ? – j2emanue May 09 '18 at 04:42
  • @j2emanue here is the link: https://support.google.com/firebase/answer/6400716 – C6Silver May 09 '18 at 06:34
  • @C6Silver how did you solve this? – cbdeveloper Jan 28 '19 at 09:38
  • @cbdev420 - With each sign-up I check if the email exists before creating an account on Firebase. – C6Silver Jan 28 '19 at 19:07
  • @C6Silver this email check you mentioned is on your Firebase database? so you are allowing multiple accounts per email on Firebase Auth? And are you using the email as a "userID" in your database (Firestore/RealTimeDB)? Thanks! – cbdeveloper Jan 29 '19 at 09:24
  • @cbdev420 - No, I am still opting to not allow it. Prior to creating a Firebase account for the user, I check the email address they are providing against email addresses for my registered users. If they match I don't allow them to register with it otherwise the process works as normal. In essence I am doing what Firebase is supposed to be doing when checking to prevent the creation of multiple accounts. – C6Silver Jan 29 '19 at 22:47
  • @C6Silver I tried to do that but I failed. Because if my user first registers with email/password, logs out and then tries to register again with Google, to do so I use the `signInWithRedirect(googleProvider)` function. The problem is that the user comes back from that redirect already signed in and at this point his password is already gone and has been replaced by the Google Sign-in Method only. Of course, once he's signed in with Google, he can create his password again. But that's really ugly user experience. How did you get around that? Do you use other function to do Google SignUp/in? – cbdeveloper Jan 30 '19 at 09:54
  • I first use `GIDSignIn.sharedInstance().signIn()` once accepted I am populating a local sign-up form as there is more data we ask for. Once that is done I check if the email given by the signin above exists. If not, I use `GoogleAuthProvider.credential` to get the credential and then `Auth.auth().signInAndRetrieveData` to create the account in Firebase. – C6Silver Jan 30 '19 at 19:31

4 Answers4

3

Go to Firebase Console

In the Authentication -> SIGN-IN METHOD

Scroll Down to Advanced Section Click on CHANGE and then SAVE

enter image description here

AndroidBeginner
  • 663
  • 1
  • 9
  • 16
  • 4
    I don't understand how this solves the issue. I do NOT want to allow multiple accounts with the same email address. This is why I choose to prevent it with the top button. I am looking for that to be enforced which Firebase isn't doing based on my description above. – C6Silver Jan 29 '17 at 19:13
  • 1
    For the heck of it I enabled the allow flow just to see what it would do. It actually does exactly the same thing as the "prevent flow". It creates an account with no email address and a UID that is different than the other account with the same email address. So both flows seem not to do what they were intended to do. – C6Silver Jan 29 '17 at 19:28
  • 1
    @C6Silver How did you solve this? I'm having similar issues. I was thinking about allowing multiple accounts per email and use the user's email as my "userID" inside my Firestore database. Since my users will have more than one UID if they create multiple accounts with the same email and different sign in methods. The email will be the only common thing between the accounts. Therefore, I'm leaning toward using the email as my "primary key". – cbdeveloper Jan 28 '19 at 09:38
  • @AndroidBeginner what would you use as a UID to identify your users? They will have a different UID on each account that they create with the same email and different sign-in methods. Ex: UID1 for email/password, UID2 for email/google, UID3 for email/facebook, UID4 for email/twitter, etc. How would you handle this? – cbdeveloper Jan 28 '19 at 09:42
2

Step 1 : Go to Firebase Console > Authentication > Sign in method. Check the option preventing multiple account creation with single email id.

Step 2 :The following documentation explains how to connect multiple providers to a single account using custom method.

https://firebase.google.com/docs/auth/web/account-linking

Kathir
  • 43
  • 4
1

@AndroidBeginner's answer helped solve this for me, however, the "Account Email Settings" option is no longer under Authentication --> Signin Method, I found it under Authentication --> Settings, and it's the first option at the top "User Account Linking".

Clicking on "Create multiple accounts for each identity provider" did solve my error in chrome console, and I am able to login/register in my app with chrome and Facebook, but now I do have multiple users with the same email...

0

Expanding Kathir's answer, Firebase documentation does provide solution.

The following are code snippets copied from the documentation.

// Step 1.
// User tries to sign in to Google.
auth.signInWithPopup(new firebase.auth.GoogleAuthProvider()).catch(function(error) {
  // An error happened.
  if (error.code === 'auth/account-exists-with-different-credential') {
    // Step 2.
    // User's email already exists.
    // The pending Google credential.
    var pendingCred = error.credential;

    // The provider account's email address.
    var email = error.email;

    // Get sign-in methods for this email.
    auth.fetchSignInMethodsForEmail(email).then(function(methods) {

      // Step 3.
      // If the user has several sign-in methods,
      // the first method in the list will be the "recommended" method to use.
      if (methods[0] === 'password') {

        // Asks the user their password.
        // In real scenario, you should handle this asynchronously.
        var password = promptUserForPassword(); // TODO: implement promptUserForPassword.

        auth.signInWithEmailAndPassword(email, password).then(function(user) {
          // Step 4a.
          return user.linkWithCredential(pendingCred);
        }).then(function() {
          // Google account successfully linked to the existing Firebase user.
          goToApp();
        });
        return;
      }

      // All the other cases are external providers.
      // Construct provider object for that provider.
      // TODO: implement getProviderForProviderId.
      var provider = getProviderForProviderId(methods[0]);

      // At this point, you should let the user know that he already has an account
      // but with a different provider, and let him validate the fact he wants to
      // sign in with this provider.
      // Sign in to provider. Note: browsers usually block popup triggered asynchronously,
      // so in real scenario you should ask the user to click on a "continue" button
      // that will trigger the signInWithPopup.
      auth.signInWithPopup(provider).then(function(result) {
        // Remember that the user may have signed in with an account that has a different email
        // address than the first one. This can happen as Firebase doesn't control the provider's
        // sign in flow and the user is free to login using whichever account he owns.
        // Step 4b.
        // Link to Google credential.
        // As we have access to the pending credential, we can directly call the link method.
        result.user.linkAndRetrieveDataWithCredential(pendingCred).then(function(usercred) {
          // Google account successfully linked to the existing Firebase user.
          goToApp();
        });
      });
    });
  }
});
Ryan Teh
  • 519
  • 5
  • 19