Firebase Phone Number Authentication

First Published: 25 May 2017
Updated on: 24 September 2018

In Google I/O17 the Firebase team made a bunch of awesome announcements, among them they released Firebase 4.0.0 which comes with a new authentication provider.

You can use Firebase Authentication to sign in a user by sending an SMS message to the user’s phone. The user signs in using a one-time code contained in the SMS message.

By the end of this post, you’ll have a working authentication system using only the user’s phone number:

  • The user will enter her phone number.
  • A reCAPTCHA box will appear to confirm humanity (this doesn’t make sense in an installable app).
  • The SMS is sent.
  • The user adds the code she received in the SMS to an alert prompt.
  • The user signs into the application.

Before we begin

NOTE: This only works for PWA, re-CAPTCHA breaks when installing on the device.

There are 2 things you need to know about phone number authentication:

  • Phone numbers that users provide for authentication will be sent and stored by Google to improve their SPAM and abuse prevention across Google services, including but not limited to Firebase. You should make sure to let your users know this, to have appropriate consent before using their phone number in the sign-in service.
  • Authentication using only a phone number, while convenient, is less secure than the other available methods because possession of a phone number can be easily transferred between users. Also, on devices with multiple user profiles, any user that can receive SMS messages can sign in to an account using the device’s phone number. Make sure to inform users of the security trade-offs of using phone number sign-in.

Firebase Phone Number Authentication

We’re going to break the process into 5 steps:

  • Activate Phone Number Authentication in our Firebase Console.
  • Set up reCAPTCHA verifier.
  • Send the SMS
  • Sign the user in.
  • Next Steps.

Make sure you grab the code on GitHub so you can follow along with the example.

We’re going to skip the app creation and connecting to Firebase processes here if you don’t know how to do it, you can check out this blog post which covers that part.

Activate Authentication Provider in Console

The first thing we need to do, is to tell Firebase that we want to use Phone Number authentication on our app, for that, you’ll want to go to the Firebase Console: https://console.firebase.google.com/ and choose the app you’re going to be using.

Inside your app’s console, you’re going to go to the authentication tab, then select the providers’ tab, and choose Phone then click on the Enable toggle as shown in the image below.

firebase phone number authentication

Setting up reCAPTCHA verifier

I had a hard time wrapping my head around they reason behind this, as I saw it, why would you need a CAPTCHA box to see if it’s a human, the fact that the app needs to be downloaded from the app store and installed in the device should be proof enough.

But then I asked someone from the Firebase team and the reply made sense, it’s not only to defend against bots, but also to prevent abuse.

There are a few 3rd party libraries out there that can be used to handle CAPTCHA, luckily we don’t need them, Firebase introduced their own reCAPTCHA implementation in the 4.0.0 release of the JS SDK.

For that to work, we just need to do a few things, first, let’s create a login page, just open your terminal (while you’re in the current project’s directory or path) and type:

ionic generate page Login

Then go to the newly generated login.html page and create an empty element to hold the reCAPTCHA verifier inside the <ion-content></ion-content> tags.

<ion-content padding>
  <div id="recaptcha-container"></div>
</ion-content>

We’re giving the <div> tag an id here recaptcha-container this is so we can make a reference to it in out code and insert the reCAPTCHA box inside it.

While we’re here, let’s also create an input to hold the phone number and a button to call for the sign in method.

<ion-content padding>
  <div id="recaptcha-container"></div>

  <ion-item>
    <ion-label stacked>Phone Number</ion-label>
    <ion-input type="number" [(ngModel)]="phoneNumber"></ion-input>
  </ion-item>

  <button ion-button id="sign-in-button" (click)="signIn(phoneNumber)">
    Sign In
  </button>
</ion-content>

Since I’m not doing any form validation at the moment, I chose to use the ngModel property to hold the data/value inside the <input /> element.

Then, we’re creating a regular button that when clicked calls the signIn() function and passes the phone number to it.

I didn’t spend much time on style since I wanted to showcase the functionality, but I did add some margins because the button was almost on top of the input element, open login.scss and add:

page-login {
  ion-item {
    margin-bottom: 32px !important;
  }
}

Now it’s time to move into login.ts to set up the reCAPTCHA verifier, the first thing we need to do is to import Firebase into the file:

import { Component } from '@angular/core';
import { IonicPage, NavController, AlertController } from 'ionic-angular';

import firebase from 'firebase';

We’re also importing AlertController because we’re going to display an alert prompt to ask for the verification code.

Create a variable to hold the reCAPTCHA verifier and inject the AlertController provider into the constructor:

public recaptchaVerifier:firebase.auth.RecaptchaVerifier;
constructor(public navCtrl:NavController, public alertCtrl:AlertController) {}

And now we’re going to use the ionViewDidLoad() lifecycle event to initialize our reCAPTCHA verifier

ionViewDidLoad() {
  this.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
}

We’re using the Firebase SDK to create a new RecaptchaVerifier and passing the <div> ID we created in the HTML file.

Send the SMS with the verification code

Now that everything is set up and ready to use, we can have our user enter her phone number and send the confirmation code to her phone via SMS.

For that we created the signIn(phoneNumber) function, we need to pass 2 parameters to the Firebase SDK to sign the user in using phone number authentication, we need the actual phone number and the result from the reCAPTCHA verifier, so let’s get that data first

signIn(phoneNumber: number){
  const appVerifier = this.recaptchaVerifier;
  const phoneNumberString = "+" + phoneNumber;

  firebase.auth().signInWithPhoneNumber(phoneNumberString, appVerifier)
    .then( confirmationResult => {
      // SMS sent. Prompt user to type the code from the message, then sign the
      // user in with confirmationResult.confirm(code).
  })
  .catch(function (error) {
    console.error("SMS not sent", error);
  });

}

We’re creating a variable to hold the reCAPTCHA verifier response, and a second variable to hold the phone number.

SIDE NOTE: I had to use const phoneNumberString = "+" + phoneNumber; because whenever I wrote the phone number in the input box “+57 300 1234567” the plus sign was being removed, and that caused an error when calling signInWithPhoneNumber saying the phone number was in the wrong format.

Then we’re passing both variables to firebase.auth().signInWithPhoneNumber() where the SDK will either send the SMS or return an error.

Sign the user In

If the SMS is not sent, just copy/paste the error code in Google or Stack Overflow, you’ll find the answer really fast.

If the SMS is sent, then we need to display an alert prompt so the user can copy the code she received in her phone

.then( confirmationResult => {
  let prompt = this.alertCtrl.create({
    title: 'Enter the Confirmation code',
    inputs: [{ name: 'confirmationCode', placeholder: 'Confirmation Code' }],
    buttons: [
      { text: 'Cancel',
        handler: data => { console.log('Cancel clicked'); }
      },
      { text: 'Send',
        handler: data => {
          // Here we need to handle the confirmation code
        }
      }
    ]
  });
  prompt.present();
})

Right there we’re displaying the alert if the user clicks cancel we will just log Cancel Clicked to the console.

If the user enters the code and clicks Send we then need to handle the code, for that, we’re going to use the confirmationResult that we’re returning in the promise: .then( confirmationResult => {...} it has a method called .confirm()

handler: data => {
  confirmationResult
    .confirm(data.confirmationCode)
    .then(function(result) {
      // User signed in successfully.
      console.log(result.user);
      // ...
    })
    .catch(function(error) {
      // User couldn't sign in (bad verification code?)
      // ...
    });
};

We use confirmationResult.confirm(data.confirmationCode) to send the confirmation code to Firebase, they take care of all of the heavy liftings for us and create the user, by the end, the entire function should look like this

signIn(phoneNumber: number){
  const appVerifier = this.recaptchaVerifier;
  const phoneNumberString = "+" + phoneNumber;
  firebase.auth().signInWithPhoneNumber(phoneNumberString, appVerifier)
    .then( confirmationResult => {
      // SMS sent. Prompt user to type the code from the message, then sign the
      // user in with confirmationResult.confirm(code).
      let prompt = this.alertCtrl.create({
      title: 'Enter the Confirmation code',
      inputs: [{ name: 'confirmationCode', placeholder: 'Confirmation Code' }],
      buttons: [
        { text: 'Cancel',
          handler: data => { console.log('Cancel clicked'); }
        },
        { text: 'Send',
          handler: data => {
            confirmationResult.confirm(data.confirmationCode)
            .then(function (result) {
              // User signed in successfully.
              console.log(result.user);
              // ...
            }).catch(function (error) {
              // User couldn't sign in (bad verification code?)
              // ...
            });
          }
        }
      ]
    });
    prompt.present();
  })
  .catch(function (error) {
    console.error("SMS not sent", error);
  });

}

And if you go to your Firebase Console, list the users, you should see a new user created with the Phone authentication provider

firebase sms auth

Next Steps

I now want you to do two things, first, test and make sure everything is working, it can get a little trickier sometimes especially when working with international clients, for example, I have 2 phone numbers, one is over 6 months old and the other one is about 2 weeks old, Firebase was not sending the SMS to my new number, just the old one.

And second, I want you to tweet at me and let me know how you plan to use this, you can find me @javebratt.

If you have any questions don’t forget you can always leave a comment below.

If you want to take a deeper dive on Ionic + Firestore you should go through my FREE course: Build your first Firestore powered Ionic app.