0
votes

I'm using Firebase in a React Native project with the RNFirebase library. I'm trying to get user phone numbers during onboarding. After initial signup with email/password the flow to get phone number is:

  1. Enter and send phone number with firebase.auth().verifyPhoneNumber(phoneNumber)
  2. Receive verification code and confirm
  3. If success, add phone number to the current auth user

So I have two methods in my component: sendCode which sends a code to the provided phone number and verifyCode which compares the code input to the code sent.

sendCode = () => {

const { phoneNumber } = this.state
firebase.auth()
  .verifyPhoneNumber(phoneNumber)
  .on('state_changed', (phoneAuthSnapshot) => {

    switch (phoneAuthSnapshot.state) {

      case firebase.auth.PhoneAuthState.CODE_SENT:
        // This ends up creating a NEW user instead of adding phone number to the current user
        firebase.auth().signInWithPhoneNumber(phoneNumber)
          .then(confirmResult => this.setState({ confirmResult }))
          .catch(err => {console.log('some other error:', err)})
        break;

      case firebase.auth.PhoneAuthState.ERROR:
        console.log(phoneAuthSnapshot.error);
        break;

    }
  }, (error) => {
    console.log(error);
  }, (phoneAuthSnapshot) => {
    console.log(phoneAuthSnapshot);
  })
}  

verifyCode = () => {
    const { codeInput, confirmResult } = this.state;
    if (confirmResult && codeInput.length) {
      confirmResult.confirm(codeInput)
        .then(user => {
          console.log(user);
        })
        .catch(err => {console.log('error verifying code:', err)})
    }
}

Following this example I am able to send the verification code, however the Promise returns and object rather than a function, which I would need to verify the code in verifyCode.

The example suggests to use firebase.auth().signInWithPhoneNumber(phoneNumber) which then returns a function to confirm the code. This did not work well as it created a new auth user rather than adding the phone number to the current user. Another problem is that the user experiences two reCaptcha challenges instead of one...

Any suggestions?

1

1 Answers

1
votes

Here's my 2 working methods that should link a given phone number to facebook or email/password auth.

verifyPhone: async phnumber => {
 try {
  let verify = await FirebaseAuth.auth()
    .verifyPhoneNumber(phnumber)
    .on("state_changed", phoneAuthSnapshot => {
      switch (phoneAuthSnapshot.state) {
        case FirebaseAuth.auth.PhoneAuthState.CODE_SENT:
          return phoneAuthSnapshot;
          break;
        case FirebaseAuth.auth.PhoneAuthState.ERROR:
          console.log(phoneAuthSnapshot.error);
          return null;
          break;
      }
    });
  return verify;
 } catch (error) {
   console.log(error);
 }
}

verifyPhone function will accept a phone number and return an object that contains your verificationId. Next is call this function,

processVerificationCode: async (verificationId, code) => {
 try {
  let credential = FirebaseAuth.auth.PhoneAuthProvider.credential(
    verificationId,
    code
  );
  let currentUser = FirebaseAuth.auth().currentUser;
  return currentUser.linkWithCredential(credential);
 } catch (error) {
   console.log(error);
 }
}

processVerificationCode function will accept 2 parameters verificationId and inputedCode, then call PhoneAuthProvider to get phone number credential. Next is to get the current logged in user (assuming you have an existing login), then from that user call linkWithCredential and pass your phone number credential.

Thats it. Hope it helps.