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 Intuit, Google 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.js, Socket.io, Express, 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!
- User attempts to log in to your website
- A random verification code is generated and the application initiates a call to the user’s verified phone number
- The user is prompted to enter the code, and given real-time feedback
- If the code is entered successfully, user is forwarded to their account dashboard
- 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:
$ npm install jade
$ npm install socket.io
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 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.
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:
$ npm install jade
$ npm install socket.io
$ npm install express
$ npm install twilio
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