Adding 2FA to a React App Using Firebase Function

Published April 01, 2020 by Kelly J Andrews
Categories:

If you’re like me, you probably have a few “smart” devices around your home. There are multiple ways to interact and control these devices, but I wanted to be able to control them with text messages and eventually voice as well.

So I set out to build some tooling in Firebase to get me going. The first step I wanted to take, however, was securing the phone numbers that have access, and I thought it would be a perfect time to try out the Verify API. It’s admittedly a bit over-the-top since this isn’t a distributed app, but for safety, a phone number must go through the verification process to access my devices.

Verify API

The Verify API is a way to confirm that the phone belongs to the user. Performing the verification helps protect against spam and suspicious activity, as well as validating ownership.

The API itself has quite a lot packed into it. Its configuration options let you build the exact workflow that works for your system. As an example, the default workflow sends an SMS with a PIN code, waits 125 seconds, then calls with a Text-to-Speech event, waits 3 additional minutes, then calls again and waits 5 minutes before expiring the request altogether.

I like having this level control over something like this as it allows me to be very specific about how I can interact with my users. In my particular instance, I kept it very simple and did just one SMS message that expired in two minutes, since I wanted this mostly for my own purposes.

If you want to get started with the Verify API, you can sign up for a Vonage account today to get going.

Firebase Functions

Since I decided on using Firebase and Firestore, setting up some Cloud Functions to interact with the data and the Verify API was my next step. Each time a new phone number was created, I wanted to send it a verification code and then have a function to check the code.

Promises, Promises

When you first learn Cloud Functions, you may try some simple operations and build your confidence, which is what I did. After going through some of the simple functions first, I figured I’d be able to build this out fairly quickly.

And I was wrong. One detail I completely overlooked is that callback methods do not evaluate in the Cloud Function environment the way they do in other environments. Once there is a returned value or promise, the CPU stops. Since the Nexmo JavaScript SDK is running on callback methods, it stops processing.

Not knowing this had to be one of the more frustrating problems I’ve run into in a long time. The timing of everything was weird because the call back would run when I tried again, causing me to think I wasn’t waiting long enough or the latency was terrible.

Once I sorted that out, I realized I needed to create Promise wrappers for the SDK methods, and everything worked perfectly. If you want some useful tips & tricks, I recommend reading this Firebase documentation guide.

Requesting the Verify Code

The Verify request method in the Nexmo JavaScript SDK is quite minimal code, as the framework there makes it simple to do most everything. The first thing I had to do was wrap it in a promise.

Creating this wrapper allows the callback method to run and return as a Promise resolution, instead of being ignored.

With this method, I could now create a Firebase function to run when the app added a new number to Firestore.

With the Verify API, we need to keep track of the request_id to use in the check process. I use this to indicate that the verification process started but not yet completed.

Checking the Verify Code

Same as the previous example, the SDK method needs to first be wrapped as a Promise.

Once the user receives it, the React application asks for the code and then calls the function directly from the application, passing the request_id, and the code.

As long as the code checks out, the document updates to include a verified flag, and the process is over. There are error status responses to check for and respond to accordingly—for example, if the code has timed out. My app currently assumes it passes.

React App

I won’t spend too much time explaining all the code I wrote for my app, but the highlights are adding the data, and then calling the Firebase function from the frontend.

In my app, I have a form to add a new number, consisting of just the phone number field. On submission, it merely adds it to the database. I’ve also set up a Firebase context file that sets the connections between my app and Firebase, so I can easily import everything I need.

The verification is nearly the same form with a similar submit method.

The Firebase SDK provides a functions export to let you use httpsCallable() and name the function. Instead of needing to write any HTTP requests and waiting on those, this simplifies the process.

Wrap Up

The Verify API is simple to use, and with Firebase and React you can quickly write the code needed to validate your users and their phone numbers. Feel free to try it out. You can sign up for a Vonage account, and if you need some credits to get you started send us an email at [email protected]

You can find my [https://github.com/kellyjandrews/smart-home-app](sample application code here). The app I built is more of a personal app for me, but feel free to have a look and use anything you might find useful. Over the next month or so, I’ll be adding some additional functionality to the app as well—first is opening and closing my garage door.

Leave a Reply

Your email address will not be published.

Get the latest posts from Nexmo’s next-generation communications blog delivered to your inbox.

By signing up to our communications blog, you accept our privacy policy , which sets out how we use your data and the rights you have in respect of your data. You can opt out of receiving our updates by clicking the unsubscribe link in the email or by emailing us at [email protected].