Check if an email already exists in Firebase Auth in Flutter App
Asked Answered
G

8

23

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?

Gobioid answered 2/8, 2018 at 11:8 Comment(0)
Q
24

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

try {
  _firbaseAuth.createUserWithEmailAndPassword(
    email: '[email protected]', 
    password: 'password'
  );
} catch(signUpError) {
  if(signUpError is PlatformException) {
    if(signUpError.code == 'ERROR_EMAIL_ALREADY_IN_USE') {
      /// `[email protected]` 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.
Quadrilateral answered 16/4, 2019 at 18:29 Comment(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? ThanksJoacima
R
22

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;
  }
}
Resurgent answered 29/6, 2021 at 19:36 Comment(3)
Google reported a security problem with FirebaseAuth.instance.fetchSignInMethodsForEmail, it is now disabled for new project (meaning this answer does not work). It is also recommened that older project disable this possiblity and are recommended not use this method.Borrego
More info: cloud.google.com/identity-platform/docs/admin/…Borrego
@Borrego Thank you for the information. I see that fetchSignInMethodsForEmail() is deprecated and Firebase recommends against using it. However, if you still want to check whether or not an email exists, I recommend to create a Cloud Function and use getAuth().getUserByEmail(email) from Admin SDK. Flutter would pass the email to the Cloud Function and the function would look up the authentication data and return the email back to Flutter.Resurgent
S
9

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.

Shirelyshirey answered 3/8, 2018 at 0:7 Comment(1)
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.Gobioid
A
5

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: "[email protected]",
    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;
 }
}
Authoritarian answered 7/9, 2021 at 6:22 Comment(0)
I
4

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.

Ioneionesco answered 18/3, 2021 at 15:36 Comment(0)
C
2

The answers would not work without some tinkering if the project is created after September 15, 2023 due to google enabling email enumeration by default.

It would have to be turned off first in firebase, see docs or through some other means as listed by this question

Cryobiology answered 11/12, 2023 at 12:44 Comment(0)
M
1

Update

PlatformException doesn't work anymore!

New Way

Check if FirebaseAuthException equals "email-already-in-use":

try {
  await FirebaseAuth.instance.createUserWithEmailAndPassword(
    email: email,
    password: password,
  );
  print("Successfully signed up!");
} catch (e) {
  if (e is FirebaseAuthException) {
    if (e.code == "email-already-in-use") {
      print("E-Mail already in use.");
    }
  } else {
    print("Other Error: $e");
  }
}
Muniz answered 29/1, 2024 at 15:7 Comment(0)
B
0
try {
  UserCredential credential = await FirebaseAuth.instance.createUserWithEmailAndPassword(email: email, password: password);
  return credential.user;
} catch (signUpError) {
  if (signUpError.toString().contains("email-already-in-use")) {
    // Action
    print("Email already in use");
  }
}
Barbwire answered 6/8, 2024 at 4:36 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.