How to Build Phone-based Two-Factor Authentication With Twilio

 Security is one of the most frustratingly vital and complex things we have to deal with in application development. On one side, we have make sure our information is protected against corruption and unauthorized access while at the same time, we need to make sure the right people have access to the right data at the right time. Failure in either direction will cause annoyance and frustration at the best of times.

While there are a variety of approaches you can take to secure the information, the first step is securing the user account itself. Two-factor authentication is the most common approach. Generally, you can use a password generating device like an RSA token but unfortunately, most people don’t have them but almost everyone has a cell phone. It is simple to set up this type of identity verification, but powerful enough that companies such as Intuit built its security validation system around an app powered by Twilio.

In our scenario, the premise is three steps:

  1. We want to collect the username, phone number, and the user’s preferred method of contact.
  2. Next, we want to generate and send that password via a second (non-email/web) channel that an attacker is unlikely to have.
  3. Finally, compare our originally generated password against the submitted password.

Building Mobile Two-Factor Authentication

First, we have a simple HTML form that collects the username, phone number, and the contact preference. In the sample code, it’s a little more complicated as I use the same form for this initial submission and for the login (step 3).

Next, we generate a password based on some random information, store it on the server, and deliver it to the user. Since we give the option to receive the message both via SMS and Voice, we make the Twilio request here. For the SMS, we display the password directly. For the Voice call, we insert spaces and commas between each character to ensure the reading pace is reasonable. Then we immediately send the user’s browser back to the login page.


Finally, once the user inputs their voice/SMS-delivered password, we validate it against the one we stored on the server. If it matches, we display a simple welcome message. If it doesn’t match, that password is invalidated and the user can begin again.

Starting from this simple example, we can build some interesting ideas:

If I was building this in the real world, I would have a slightly different interaction. When the user requested a password on the first step, instead of trusting the number they specify, I would use the phone number on their existing customer account.

Alternatively, I may only use two-factor in certain situations. An e-commerce site may only require a second factor when a user attempted to update their billing information, change their shipping address, or change their password.

With just a few dozen lines of code and some careful consideration, we can come up with a variety of ideas that balance the usability of the system while protecting its important pieces.