How to check if phone number is already registered in firebase authentication using flutter

Viewed 4192

So i am making a simple sign up and login screens in flutter application that uses phone authentication of firebase. For sign up im able to register new user, as the user provides his phone number and gets OTP. But for login i wanna check if the entered number is already registered. If so he gets otp and logs in or if not registered then asks to sign up first.

3 Answers

Firebase admin SDK supports this. Here's how to set up firebase admin (documentation). After you set up admin, you can use cloud_functions package to call APIs from the firebase admin SDK and the API we'll be using is one that allows us to get a user by phone number (documentation). If the API response is a user record, we know a phone exists.

In this example, I'm using node.js. In functions/index.js:

exports.checkIfPhoneExists = functions.https.onCall((data, context) => {
   const phone = data.phone
   return admin.auth().getUserByPhoneNumber(phone)
    .then(function(userRecord){
        return true;
    })
    .catch(function(error) {
        return false;
    });
});

In your dart code:

final HttpsCallable callable = CloudFunctions.instance.getHttpsCallable(functionName: 'checkIfPhoneExists');
dynamic resp = await callable.call({'phone': _phone});
if (resp.data) {
    // user exists
}

Once the OTP is sent to the user you can verify if the user is a new user or an existing one in verify OTP function

verifyOtp(String input, context) async {
  String retVal = "error";
  OurUser _user = OurUser();
  print(input);
  final AuthCredential credential = PhoneAuthProvider.credential(
      verificationId: _verificationId, smsCode: input);
  try {
    //  await _auth.signInWithCredential(credential);
    UserCredential _authResult = await _auth.signInWithCredential(credential);

    // Here i have to save the details of the user in the database
    if (_authResult.additionalUserInfo.isNewUser) {
      currentUser.uid = _authResult.user.uid;
      currentUser.phone = _inputText;
      currentUser.type = "Customer";

      retVal = await OurDatabase().createUser(currentUser);
    } else {
      // get the information of the user from the database this already exists
      currentUser = await OurDatabase().getUserInfo(_authResult.user.uid);
      if(currentUser!= null) {
        Navigator.pushNamedAndRemoveUntil(
            context, "/homescreen", (route) => false);
      }
    }
    print("End of the await");

    // when signup with the otp
    if (retVal == "success") {
      print("why not inside this mane");
      Navigator.pushNamedAndRemoveUntil(
          context, "/homescreen", (route) => false);
    }

    saveAllData();
  } catch (e) {
    print(e);
    print("Something went wrong");
    //prin
  }
}

Now this is when you want to verify OTP from the user and after the top is verified you can know if the user was indeed a new user or an old one but what if you wanted to know that beforehand then the best possible solution would be to create a new collection in the firestore that would have only one document(so you are charged only for one document read) that would just contain all the numbers of the users that are registered within your application,

I used a simple straight forward way and it worked just fine. First, add the mobile number to the firebase database in a separate node when the user creates the account.

 await dbref.child("RegisteredNumbers").push().set({
        "phoneNo": FirebaseAuth.instance.currentUser!.phoneNumber,
      });

whenever a user tries to log in or signup check in this node if the provided number is available in It or not.

 Future<bool> checkNumberIsRegistered({required String number}) async {
    bool isNumberRegistered = false;
    try {
      await dbref.child("RegisteredNumbers").once().then((data) {
        for (var i in data.snapshot.children) {
          String data = i.child("phoneNo").value.toString();

          if (number == data) {
            isNumberRegistered = true;
            return isNumberRegistered;
          } else {
            isNumberRegistered = false;
          }
        }
      });
      return isNumberRegistered;
    } catch (e) {
      return false;
    }
  }

Hope it helps

Related