Implementation of Two-Factor Authentication with TOTP using Speakeasy

What is Two-Factor Authentication (2FA)?

Two-factor authentication which is called two-step verification or dual-factor authentication is a security process to better protect users and resources by asking users to verify identity in two ways.

There are several ways to do this. The most common one is a knowledge factor or something the user knows like password, pin, and security question. A possession factor is something the user has such as an ID card, Security Token, or Mobile Device. An inherence factor or biometric factor is something physically inherent in the user like fingerprints, facial or voice recognition.

The two-factor authentication process required two factors in two different categories. For instance, a locked email account might ask security questions based on the knowledge factor and then send a code to a mobile device or the email account which are recorded as the possession factor. Similarly, when facial recognition, a biometric factor fails in your mobile phone it typically asks for a pin code and not the fingerprint which would be another biometric factor. Two-factor authentication is much more secure than single-factor authentication. Most single-factor services are password-based.

There are multiple ways to receiving the security token and the most common ways are getting the token via email, SMS, or via an Authenticator app such as Google Authenticator, and Microsoft Authenticator, but this article will focus only on getting the secret key via an authenticator app and the implementation of 2FA using the npm packages, “speakeasy” and “qrcode”.

The below chart represents the basic flow of the two-factor authentication process which is followed in this article.

Before moving onto the implementation, let’s get a brief idea of the One-Time Password (OTP) algorithms.

One-time passwords are passwords that we use once and we never use them ever again. These passwords can be used every time we want to authenticate and whether we get an authentication code correct or incorrect we are never going to use the same OTP again.

The one common way of providing this One-Time Password is HOTP that stands for HMAC-based One-Time Password. It uses a keyed-hash message authentication code (HMAC). This message authentication code is something that is gonna pop up on the screen and based on the secret key and the counter that is in place. And this message is going to be used as the One-Time Password. Commonly this HOTP method is used in Token-based authentication and the value of the hash is different every time.

The other way of providing this One-Time Password is the Time-based One-Time Password (TOTP) and this is the method we are going to practice in our implementation. In TOTP, you are going to get a certain password at whatever time of the day happens to be. In this scenario, time synchronization is very important since the secret key is configured ahead of time. Timestamps are synchronized via a protocol which is known as Never Time Protocol (NTP). This Timestamps usually increments every 30 seconds and this value can be changed by the administrator. So when you are logging in to the system you have to put your username, password, and the latest TOTP code.

The npm package, “speakeasy” can be used to implement both HOTP and TOTP algorithms, but in this article, I’ll be focusing on TOTP.

As I previously mentioned above you have multiple ways to get the token and in this scenario, I’ll explain the way of implementation of the 2FA process for getting the token via an authenticator app. In the initial setup, the server generates the secret key and provides the generated QR code to the client-side. Then the client has to scan the QR code using an authenticator app such as Google authenticator and provide the token for the verification. After that in each logging, the client has to provide the stored token and verify against the secret.

Let’s move onto the 2FA implementation process.

Install

First, you have to install two npm packages, “speakeasy” and “qrcode” into your project.

Inside your project folder do:

npm install --save speakeasynpm install --save qrcode

Step 1: Generate A Secret

The “generateSecret” method in “speakeasy” returns the secret key with multiple encodings such as ASCII, hex, Base32, and otpauth_url. The otpauth_url is used later in this 2FA implementation process.

After generating the secret object you have to store it in your database with the user’s username or email that would uniquely identify the user.

Step 2: Displaying a QR Code

You can get the customized URL for SHA512 with the name of your company by using the otpauthURL() method. Then you’ll be able to see the token in the authenticator app with the label that you have provided in the code.

Using the toDataURL() method in the qrcode package you can generate the PNG data URL for the otpauth_url. In this scenario, pass the “qrurl” that is generated using the above code. Important! generate the data URL on the server-side since it is not secure passing the secret key to the client-side.

Step 3: Verifying the Token

After all, we want to verify whether the token on the client-side matches with the secret on the server-side or not. The verify() method can be used to check the secret against the token.

First, the user has to scan the QR code displayed on the screen using an authenticator app such as Google authenticator, Microsoft authenticator. Then ask the user to input the token that they can see in their app.

Here the window represents the time-step. The default value of time-step is 30 minutes, but if the window size is 1 user can verify the token within +/- 1 minute from the server.

The value of verified is true if the given token matches with the secret, false if not. If successfully verified you can update the saved secret in the database and the verified flag is true. Then you can use the same secret while logging into the system and you only want to enter the token you can see on the app.

Conclusion

Wow! you put the first step in implementing 2FA. So these are the three main steps that you can follow while implementing the 2FA. In a further implementation, you have to consider the endpoints and front-end implementation methods based on your application scenario.

I hope this article gave you a basic idea of what 2FA is and how to implement 2FA.

Happy Coding!

Computer Science & Engineering Undergraduate at University of Moratuwa