19

I'm currently developing a flutter app that requires users to register before using it. I use Firebase Authentication and would like to check whether an email is already registered in the app.

I know the easy way to do it is to catch the exception when using the createUserWithEmailAndPassword() method (as answered in this question). The problem is that I ask for the email address in a different route from where the user is registered, so waiting until this method is called is not a good option for me.

I think the best option would be to use the method fetchProvidersForEmail(), but I can't seem to make it work.

How do I use that method? Or is there a better option to know if an email is already registered?

Derrick
  • 3,669
  • 5
  • 35
  • 50
Iule
  • 313
  • 1
  • 2
  • 8

5 Answers5

20

The error raised is a PlatformException so you can do something as follows-

try {
  _firbaseAuth.createUserWithEmailAndPassword(
    email: 'foo@bar.com', 
    password: 'password'
  );
} catch(signUpError) {
  if(signUpError is PlatformException) {
    if(signUpError.code == 'ERROR_EMAIL_ALREADY_IN_USE') {
      /// `foo@bar.com` has alread been registered.
    }
  }
}

The following error codes are reported by Firebase Auth -

  • ERROR_WEAK_PASSWORD - If the password is not strong enough.
  • ERROR_INVALID_EMAIL - If the email address is malformed.
  • ERROR_EMAIL_ALREADY_IN_USE - If the email is already in use by a different account.
Sakchham
  • 1,689
  • 12
  • 22
  • 1
    Can you please let me know how to handle Facebook/google log in? Like if the user is trying for a Facebook login then how to verify that, that particular user is a new one or an old one? Thanks – Rajat Mishra Oct 08 '20 at 06:13
20

There is no such fetchProvidersForEmail method anymore in the current version of the firebase auth package. The equivalent one is now fetchSignInMethodsForEmail method which I think would be the best option to handle this case without executing any unnecessary operation.

fetchSignInMethodsForEmail

In docs, it's stated that this method returns an empty list when no user found, meaning that no account holds the specified email address:

Returns a list of sign-in methods that can be used to sign in a given user (identified by its main email address).

This method is useful when you support multiple authentication mechanisms if you want to implement an email-first authentication flow.

An empty List is returned if the user could not be found.

Based on this, we could create our own method like the following one:

// Returns true if email address is in use.
Future<bool> checkIfEmailInUse(String emailAddress) async {
  try {
    // Fetch sign-in methods for the email address
    final list = await FirebaseAuth.instance.fetchSignInMethodsForEmail(emailAddress);

    // In case list is not empty
    if (list.isNotEmpty) {
      // Return true because there is an existing
      // user using the email address
      return true;
    } else {
      // Return false because email adress is not in use
      return false;
    }
  } catch (error) {
    // Handle error
    // ...
    return true;
  }
}
Stewie Griffin
  • 4,690
  • 23
  • 42
7

I think the only possibility from within the app is attempting a login (signInWithEmailAndPassword) with that e-mail and check the result.

If it's invalid password, the account exists. If it's invalid account, the account do not exist.

Error 17011
There is no user record corresponding to this identifier. The user may have been deleted
Error 17009
The password is invalid or the user does not have a password

As this is a kind of an ugly solution, you can justify this additional call using it to check it the e-mail formatting is correct (according to the firebase rules). If it doesn't comply it will throw a address is badly formatted and you can alert the user soon enough.

You can do these checks using the error codes with current versions of the plug-in.

Feu
  • 5,372
  • 1
  • 31
  • 57
  • That would do the trick, I guess. It would be best if the method I mentioned earlier worked, but in the meanwhile this does roughly the same. Thank you. – Iule Aug 03 '18 at 06:49
4

I didn't think fetchProvidersForEmail() method is available in the firebase package. So we can show the appropriate message to the user. you can create more case if you need.

try {
  await _auth.signInWithEmailAndPassword(
    email: "Hello@worl.com",
    password: "123456789"
  );
} catch (e) {
  print(e.code.toString());
  switch (e.code) {
    case "email-already-in-use":
    showSnackBar(context,"This Email ID already Associated with Another Account.");
    break;
 }
}
iqfareez
  • 555
  • 7
  • 21
Shailendra Rajput
  • 2,131
  • 17
  • 26
3

There are many ways you can do that. As Sakchham mentioned, you could use that method. There is another method you could use which in my opinion is better and safer.

Since the password value will return ERROR_WEAK_PASSWORD, it is a create account method which you are calling which means that it's possible an account will be created if the account doesn't exist, in that case, I recommend personally using the sign in with email method.

I used this code below:

Future<dynamic> signIn(String email) async {
    try {
      auth = FirebaseAuth.instance;      
      await auth.signInWithEmailAndPassword(email: email, password: 'password');
      await auth.currentUser.reload();
      return true;
    } on FirebaseAuthException catch (e) {
      switch (e.code) {
        case "invalid-email":
          return 'Your username or password is incorrect. Please try again.';
          break;
     }
   }
 }

Leave down a comment if you have any suggestions.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Ziyad
  • 354
  • 4
  • 13