Two-Factor Authentication with Node.js and Twilio

Two-factor authentication is becoming the go-to method for increased login security on the web, as it ties a physical device to your virtual credentials. It is being adopted by many of the major players in the industry, including IntuitGoogle and Facebook. While user security is paramount, modern web developers must also consider the UX problems that can arise from increased security measures.

Since UX is becoming increasingly important, I set out to design a more interactive and more modern method of two-factor authentication. In this post, I’ll outline how you can implement an interactive two-factor authentication solution using Node.jsSocket.ioExpress, and Node-Twilio (3rd-party). If you are interested in a solution using PHP and jQuery, please check out this past blog post. I will highlight the most important parts of implementing an interactive solution in this blog post, and if you’re interested in playing with a fully functional demo please fork my repository on GitHub!

Steps

  1. User attempts to log in to your website
  2. A random verification code is generated and the application initiates a call to the user’s verified phone number
  3. The user is prompted to enter the code, and given real-time feedback
  4. If the code is entered successfully, user is forwarded to their account dashboard
  5. If the code is entered incorrectly, the user must log in again

Step One: Getting Started

To get started, you will need a public web server with Node.js installed. If you are new to Node.js, I recommend reading our article on Getting Started with Twilio and Node.js, as it explains how to get running for the first time. Once you have that all set up, you will need to install a couple of additional packages by running the following commands in your Terminal:

[code lang="bash"]
$ npm install jade
$ npm install socket.io
[/code]

Step Two: Frontend

Now that your environment is all set up, we can start writing our app. The first step is to write the Jade template code that will generate the HTML for your login page. Create a folder called ‘views’ and a file named index.jade within it. The following code goes in that file:
This code may look somewhat daunting if you are not familiar with Jade, but in reality most of the tags correspond directly to standard HTML tags, with shorthand for setting IDs and Classes for CSS styles. For example, div.myclass#myid is essentially the same as writing ‘<div id=”myid” class=”myclass”></div>’ You may also notice that I am including the JavaScript and CSS files for Twitter Bootstrap. This is purely for the purpose of making this demo look more visually appealing. If you wish to include this portion of the application, you can download the bootstrap files and extract them into the ‘bootstrap’ directory within your main application directory.

Now that we have defined the look and feel of our hypothetical login form, we can now add the frontend JavaScript that will make it feel interactive to the end user. I’m going to split the JavaScript code into multiple parts and explain each snippet individually so that it will be clear what is going on.

This code handles the submission of the form (when the user clicks the Log In button). It first prevents the actual submission event, which by default makes a POST request to the address specified in the ‘action’ parameter of the <form> tag. We then emit three socket events, each with a specific action. The first and second send the username and password data along to the server and the third sends along the user’s phone number. If this example were running in production you would likely have the user’s phone number saved in the database along with their account information, but for the purposes of this demo we will specify it in the login form.

This next snippet of code handles the ‘newcode’ event, which is sent from the server to the client upon generation of a new verification code. This handles the display of the code on the frontend and the initialization of all CSS classes associated with it so that the user can get started with the authentication process. And this last, larger snippet of JavaScript code handles the events associated with the actual authentication process. When each digit is entered, the server checks to see if the code is valid and then emits the proper socket event so that the user can see a real-time visual response. Now that the frontend portion of this application is complete, I recommend checking out the entire index.jade file so that you can see how all of the pieces fit together.

Step Three: Backend

Now, in your main application directory, create a file called app.js – this is the primary Node.js application file. The first portion of this file deals with configuration of Express, User Sessions, and Node-Twilio. You will need to make changes here and include your Twilio account credentials, your server hostname, and the outgoing phone number that you will be using for verification. You can also change the session secret and key as well as the application port, though it is not necessary in order to run the demo.

This next snippet of code handles the events that are emitted when the user clicks on the Log In button on the frontend. It demonstrates how you can save the username and password into session data. In a production application, I would recommend encrypting the password on the frontend and NOT storing it in session information. However, to show how session data is stored and retrieved I have included it in this tutorial. And now for the fun part! This session event ‘init phone’ is emitted when the user logs in, and it handles the initiation of the phone call to the end user so that they can authenticate themselves. The first important thing to notice are that you can change the length of the verification code merely by modifying a variable, ‘codelength’. The second thing to notice is that rather than defining a callback URL that renders TwiML (such as in the PHP, Ruby, or Python helper libraries), in Node.js this URL is generated and passed along dynamically. This creates a unique event-based flow where we can simply say that when a call is ‘answered’ we want to execute the following code. Within this event handler we also Gather the first Digit that the user enters for their verification code.

The last portion of our Node.js application is a function that handles each Digit that the user enters. It is a recursive function that verifies each Digit as it is entered and emits the proper events so that the user sees real-time feedback on the frontend. Since we are Gathering a single Digit at a time, the user experience feels as if the user is interacting with the login form in real time.

Now that we have gone over each portion of our app.js file in detail, I recommend checking out the final file so that you can see how all of the pieces fit together.

And that’s it! I’d like to thank Daniel Baulig for his sample application on using sessions in Express, which was used as the starting point for this project.

If you would like to try the completed and functional demo application, you can download it here. Note that to run the demo, you will first need to run the following commands from within your application root directory:

[code lang="bash"]
$ npm install jade
$ npm install socket.io
$ npm install express
$ npm install twilio
[/code]

You can also find the full, up-to-date source on GitHub here.

Read more about Phone Verification

Documentation: Twilio documentation for Two-Factor Authentification

Blog post: How to Build a Phone-Based Two-Factor Authentification 

Blog post: Phone-Based Two-factor Authentication Is A Better Way to Stay Secure

Blog post: The Key to Phone Verification is a Good User Experience

If you have any feedback, comments, or suggestions please e-mail me at jonmarkgo@twilio.com or tweet at me @jonmarkgo.