How to implement Two-Factor Authentication using Next.js, Twilio and Altogic
Tags: javascript, webdev, react, nextjs
Published: 2022-05-13 12:43:23

## Introduction

This article will cover **two-factor authentication** basics using [Next.js](https://nextjs.org/), [Twilio](https://twilio.com/), and [Altogic](https://altogic.com/), a Backend-as-a-Service platform using its client library. This authentication method allows users to add one more security layer to their application. Many people enable their **two-factor authentication** settings to increase their security using their phone numbers or authentication apps for security purposes.

You can check out the [source code](https://github.com/altogic/altogic/tree/main/examples/nextjs-two-factor-authentication) and [demo app](https://altogic-nextjs-two-factor-auth.vercel.app/).

### How is the two-factor authentication flow?

 1. Users who already have an account need to set their phone number to enable two-factor authentication.

 2. An SMS with a code is sent to the specified phone number by **Altogic and Twilio**.

 3. Users verify their phone number by entering the code sent to their phone number.

 4. Users can enable or disable the two-factor authentication setting from their profile.

 5. When users try to sign in, if two-factor authentication is enabled, a code is sent to the specified phone number by **Altogic and Twilio.**

 6. Users verify their identity by entering the code on the input on the screen.

 7. If two-factor authentication is not enabled, they can sign in without this process.

## Youtube Showcase Video
{% embed https://www.youtube.com/watch?v=iZHgR1_W8vk %}
## Set up the Project

This project builds on top of the complete e-mail authentication app we created previously. You can follow the [tutorial](https://medium.com/altogic/altogic-email-authentication-with-next-js-and-altogic-4c036c36ea8f) to build the same app or clone the project from [here](https://github.com/altogic/altogic/tree/main/examples/nextjs-email-authentication) and continue with the rest of the tutorial.

## Twilio Integration

You need to sign up for **Twilio** with a free/paid trial. You need to get the **Account SID** and **Auth Token** for integration with Altogic Client Library.

If you use the free trial, you will need to take the **Twilio** phone number to send SMS messages to the users.

 1. Create an Account on *Twilio*

 2. Open **Console**

 3. Click “Get a trial phone number” on the left-top of the Console

 4. Copy **Account SID**, **Auth Token,** and **My Twilio phone number** values to the clipboard

![Twilio Credentials](https://cdn-images-1.medium.com/max/2800/0*Fjkgv5P9FCTkF62u.png)

Now, we’ve copied the configuration credentials to the clipboard. You must specify the verified phone numbers in trial accounts, which we defined as “ *to number”* in **Altogic**.

 1. Click on the **Explore Products** in the left sidebar.

 2. Be sure that **Messaging** and **Phone Numbers** products are selected.

Now you can navigate to the **Verified Caller IDs** page by **Sidebar → Phone Numbers → Manage → Verified Caller IDs.**

![](https://cdn-images-1.medium.com/max/2000/0*uyjZHk6tFYytA34Y.png)

You should add your phone number as a Verified Caller from here.

And finally, you have to give geo permission to your phone numbers region. You can go to this page by **Sidebar** → **Messaging** → **Settings** → **Geo permissions.**

![](https://cdn-images-1.medium.com/max/2000/0*-PLQ3y-NeudqR2hg.png)

## Create the models

Models define the **data structure and data validation rules** of your applications. A model is composed of **basic**, **advanced,** and **sub-model** **fields**. As an analogy, you can think of models as tables and fields as columns in relational databases or models as documents and fields as document properties in non-relational databases.

![Key entities in Altogic](https://cdn-images-1.medium.com/max/3590/0*jOvv0K2lUO1dk6Ro)

When we create our application, **a user model is created** by default. We need to add a **boolean field** to this user model to let users **enable** and **disable** the two-factor authentication.

To create a field via the Designer, you need to **Navigate to Models** view and select the model you would like to add the new field. You will be directed to the model details view.

![](https://cdn-images-1.medium.com/max/5368/1*wNMd344wRFEmdVWm-WXppg@2x.png)

 1. In the model details view, select **New field.**

 2. From the dropdown menu, **select** the **Boolean** that you would like to create.

 3. In the field name, type “**twoFactorAuth**” and set a default value of false

 4. Select **Create**

![](https://cdn-images-1.medium.com/max/2392/1*vbZntcm568IFmlTnqFn00g@2x.png)

We need to create a new model called **phoneVerificationCode** to handle the verification code we send to users’ phone numbers. This data type will be a **Transient** data type meaning it is not stored in the database. We are defining it as **Transient** because we don’t need it after completing the verification.

To create a model via the Designer, you have two options. You can either create a model from scratch or a sample JSON document. In either case, first, you need to navigate to the **Models view** in designer and select **+New**.

![](https://cdn-images-1.medium.com/max/5364/1*sDm3NGTyXTUxQryR4Wb2fw@2x.png)

After, you can pick a **Model**.

![](https://cdn-images-1.medium.com/max/2392/1*6VQM6b2shrdweT_o80UTfQ@2x.png)

And create the **phoneVerificationCode** model. Afterward, we need to add three fields:

 1. **code** field, which is an **Integer**.

 2. **userId** field, which is an **Object reference** to the **users** model.

 3. **phoneNumber** field, which is a **Text** field.

![](https://cdn-images-1.medium.com/max/5360/1*iE7PaDia0KjitAUL75EE9A@2x.png)

## Create the endpoints

**Endpoints** are the communication channels to access the services provided in your applications, and through endpoints, you **expose** your application services and data **to the outside world**.

To create an endpoint via the Designer, you need to navigate the **Endpoints view** in designer and select **New->Endpoint.**

![How to create endpoints in Altogic Designer](https://cdn-images-1.medium.com/max/10240/1*l4aFW2BIB7BvOVo7V35RvQ.png)

After clicking, you need to enter a relevant endpoint name and optionally pick a group, pick a method, specify the path and assign a service that handles the requests to the endpoint.

We can also click on the “Session required” checkbox, which enforces a need for a session when a request is made to the endpoint.

![](https://cdn-images-1.medium.com/max/2384/1*29q_MAhK1YNGR8lz8XmawQ@2x.png)

In this example, our method is “**POST**,” and our path is “**/users/set-phone**” meaning that if we send a **POST** request to this path, the service we define will run. We created a service by clicking “**Add new service**” and by naming our service, we will be created an empty service. We will design the service next.

![](https://cdn-images-1.medium.com/max/2384/1*6q82ovkRXn1WhRQetBXn-w@2x.png)

We will create **three more endpoints** to verify the code while changing the phone, signing in, and implementing the particular sign-in functionality.

Create the verify code during changing phone endpoint:

![Verify code during changing phone endpoint](https://cdn-images-1.medium.com/max/2380/1*5GPJRB0kJ_ig2iFsiEIFeg@2x.png)

Create the verify code during the sign-in endpoint:

![Verify code during sign-in endpoint](https://cdn-images-1.medium.com/max/2384/1*vCLguYn61c4uREcRAlUpfQ@2x.png)

Create the sign-in endpoint for implementing the particular 2-FA logic:

![Sign in endpoint for implementing the specific 2-FA logic](https://cdn-images-1.medium.com/max/2392/1*ebDWbWzWx2uoAMR5SKvCrg@2x.png)

Now that we created our endpoints and services, we can start **designing** the services, which is the **most fun part** of using **Altogic**!

## Design the Services

Building the flow of service involves three main activities.

 1. Adding the right node from the **nodes library** to the **service flow area.**

 2. Customizing the added node parameters using the **node properties panel.**

 3. Linking the **output link point** of a node to the **input link point** of another node using relations.

First, we will implement the **“Set phone number service.”** We have the start node, which is used to start the execution of the endpoint handling service. It runs only once at the start of the service to trigger nodes connected to its output link point. We define a query string parameter of type text named “phoneNumber” as input for this endpoint.

![](https://cdn-images-1.medium.com/max/2924/1*nkDzaz6-j9lRJT53Bc22SA.png)

Then, we check if the phone number sent is a valid phone number with the **ISMOBILEPHONE()** function.

![](https://cdn-images-1.medium.com/max/3052/1*D-_W4oUTdXQkizH4ZWiCXg.png)

If no, return an error response.

![](https://cdn-images-1.medium.com/max/2916/1*A1CFsOtXQZaDurzdaN8Yzg.png)

If yes, create an object of **phoneVerificationCode** model. For code, we generate a random number with **RANDBETWEEN()** function and insert the other fields from either the input or the session.

![](https://cdn-images-1.medium.com/max/3044/1*LKXs8nX-jsK_wG2y-nxuRw.png)

Cache the object we created so we can access it later for verifying the code. I want the code to expire after one minute, so I set the timeout value to 1 minute.

![](https://cdn-images-1.medium.com/max/3228/1*HR3DBjnvxS2kIVQtR6H7FA.png)

Send the SMS message to the specified phone number with the code. Here we use the Twilio credentials we obtained.

![](https://cdn-images-1.medium.com/max/3120/1*B3JEBKCDPgUHRyXPBUcrHQ.png)

Then we return the success response. This is the final look of our service:

![](https://cdn-images-1.medium.com/max/3316/1*zcPAj4TcKj0-0fs6krdOvw.png)

Next, we will implement the **“Verify code in change phone service.”** This service is used to verify the code when users want to change their phone numbers.

We have the start node, which is used to start the execution of the endpoint handling service. It runs only once at the start of the service to trigger nodes connected to its output link point. We define the request body structure as a single model of “**phoneVerificationCode**” as input for this endpoint.

![](https://cdn-images-1.medium.com/max/2940/1*RNo9Q67RMaiKk1hWMY36nw.png)

Get the cached object with the phone number to check the code.

![](https://cdn-images-1.medium.com/max/2936/1*a9xgDJadobGlYRWCCS5CiQ.png)

Return an error response if the cached object does not exist anymore. It means that the code is expired and no longer valid.

![](https://cdn-images-1.medium.com/max/2844/1*MVUdDWSl5nQeschEDgnn7Q.png)

Check if the cached code is **equal** to the code sent in the “**phoneVerificationCode**” object.

![](https://cdn-images-1.medium.com/max/2976/1*MyE-KwLMtZt0n5HT9I-DsQ.png)

Update the user's phone number and set the “**phoneVerified**” to true using the “**Update Object Fields by Id**” node. We need to set the updated object model to “**users**” and object id to the userId, and we do that by giving the **userId** we obtain from **phoneVerificationCode** object.

![](https://cdn-images-1.medium.com/max/2932/1*W-x8CF5gbpXvPusHGMA5TA.png)

Then we return the success response. This is the final look of our service:

![](https://cdn-images-1.medium.com/max/2932/1*k9o3tH28zaHaeJpKL_droA@2x.png)

Next, we will implement the **“Verify code in sign-in service.”** This service is used to verify the code when users try to sign in when their two-factor authentication is enabled.

We have the start node, which is used to start the execution of the endpoint handling service. It runs only once at the start of the service to trigger nodes connected to its output link point. We define the request body structure as a single model of “**phoneVerificationCode**” as input for this endpoint.

![](https://cdn-images-1.medium.com/max/2780/1*k2FpvseVrlnmQgLil6nT2g.png)

Get the cached object with the phone number to check the code.

![](https://cdn-images-1.medium.com/max/2912/1*rC2PZbcgE_9WqmJ4gCbObQ.png)

Return an error response if the cached object does not exist anymore. It means that the code is expired and no longer valid.

![](https://cdn-images-1.medium.com/max/2844/1*MVUdDWSl5nQeschEDgnn7Q.png)

Check if the cached code is **equal** to the code sent in the “**phoneVerificationCode**” object.

![](https://cdn-images-1.medium.com/max/2936/1*Jmd6ST-imyKzq7mshzZIoA.png)

Return error if code is not equal to the one sent in the input.

![](https://cdn-images-1.medium.com/max/2860/1*rgvY5C6syY_Ty7ZynInoMg.png)

Get the user using the “**Get Single Object by Query**” node. We need to set the **retrieved object model** to **users,** and our query should be this.phone==inputObject.phoneNumber to get the user with the specified phone.

![](https://cdn-images-1.medium.com/max/2912/1*sr7d0cpMHrA0R5QRARRhLw.png)

If there is no user, return an error response.

![](https://cdn-images-1.medium.com/max/2708/1*DLpzhDesjEV1F6FMF8V_Fw.png)

If there is a user, create a user session.

![](https://cdn-images-1.medium.com/max/2864/1*1MUgIL6ewWHScyPljyKDEg.png)

Then we return the success response. This is the final look of our service:

![](https://cdn-images-1.medium.com/max/3372/1*nX5kVhHiQ5sKap6py5R32g@2x.png)

Next, we will implement the **“Sign in service.”** This service is used to implement the sign-in feature. Because we want to use two-factor authentication, we can’t use the function in the client library, and we have to design it ourselves. But don’t worry, designing complex business logic in **Altogic** is relatively easy! :)

We have the start node, which is used to start the execution of the endpoint handling service. It runs only once at the start of the service to trigger nodes connected to its output link point. We define a query string parameter of type email named “**email**” and type text called “**password**” as input for this endpoint.

![](https://cdn-images-1.medium.com/max/3024/1*gEt0rT29AtvAVAWMcvRRug.png)

Get the user using the “**Get Single Object by Query**” node. We need to set the **retrieved object model** to **users,** and our query should be this.email==params.body.email to get the user with the specified email.

![](https://cdn-images-1.medium.com/max/2856/1*vXyzYdQd-IXo9RNPrRavBQ.png)

Return an error if there is no user with the specified email.

![](https://cdn-images-1.medium.com/max/2640/1*smuLN2HkfsNLmtQnunwdBw.png)

Use the **“If-Else Condition**” node to check if the emailVerified field of the user is true or not.

![](https://cdn-images-1.medium.com/max/2804/1*pJis4ccGRiuOmE4eoIuLiQ.png)

If the email is not verified, return an error response.

![](https://cdn-images-1.medium.com/max/2816/1*kkDs3gEcOUf3s819Mft_gA.png)

Compare the password sent with the password in the database with **ECOMPARE()** function. This function compares the password text in the input with the password in the database but **does not expose** the encrypted password. No one, including the developer, can see the user's passwords.

![](https://cdn-images-1.medium.com/max/2836/1*V5SaHpMIjVkA5MncU74Mqw.png)

Return an error response if passwords do not match.

![](https://cdn-images-1.medium.com/max/2744/1*GwqEcn7G3izZMxJRUry-Fw.png)

Check if the **two-factor authentication** of the user is enabled.

![](https://cdn-images-1.medium.com/max/2648/1*-K5POX5meS0vgJYMCG7ZGg.png)

If two-factor authentication of the user is not enabled, create the user session and return it with the user data.

![](https://cdn-images-1.medium.com/max/2852/1*HN4mcUgqwbM3N-MgugRmwg.png)

If enabled, create an object of **phoneVerificationCode** model. For code, we generate a random number with **RANDBETWEEN()** function and insert the other fields from the input.

![](https://cdn-images-1.medium.com/max/3284/1*EZAwI3iGsquthZ8syGCwcw.png)

Cache the object we created so we can access it later for verifying the code. I want the code to expire after one minute, so I set the timeout value to 1 minute.

![](https://cdn-images-1.medium.com/max/2996/1*KCckXGETVD4z3I-Fzg6W4w.png)

Send the SMS message to the specified phone number with the code. Here we use the Twilio credentials we obtained.

![](https://cdn-images-1.medium.com/max/2924/1*hG0LEpSjCwtYbrcUFm4MOQ.png)

Then we return the success response. This is the final look of our service:

![](https://cdn-images-1.medium.com/max/4916/1*_FPVaXTVi8QhUZoGVuNqTA.png)

To learn more about building the service flows, check out the [documentation](https://docs.altogic.com/help-guides/building-services/service-flow).

## Let’s Start Coding!

### Set/Change phone functionality

To enable two-factor authentication, users need to set up their phone numbers. This functionality is the same as **changing the phone functionality** so that we will use the same screen with some minor conditional UI changes.

We have already created the endpoint and designed the service. We need to send a request to the endpoint using **Altogic Client Library** using **EndpointManager** and the post method like **altogic.endpoint.post()**
{% gist https://gist.github.com/mertyerekapan/253d0cc73d5e11818828823d17669960.js %}
### SMS verify during change phone functionality

Code above runs the service for setting/changing the phone number and sending the SMS for verification code. Now, users need a screen to enter the SMS code. We have already created the endpoint and designed the service for this case. We need to send a request to that particular endpoint.

Here is the code for that:
{% gist https://gist.github.com/mertyerekapan/49152b4694e48ddb39f7468455ce553f.js %}
### Toggle Two Factor Authentication functionality

Users should be able to switch on and off two-factor authentication if they want to. For this, we are implementing a basic switch. We are updating the **twoFactorAuth** boolean field.
{% gist https://gist.github.com/mertyerekapan/e6a80b3e76440bc7b2b33a32ee1635af.js %}
### Sign in functionality

When users want to sign in, we will use the service we designed because we need to check if two-factor authentication is enabled and if yes, we need to send an SMS with a code. We replace the client library function with sending a request to the endpoint.
{% gist https://gist.github.com/mertyerekapan/6da18eec493ee77ae09c50e6f7dfd36d.js %}
### SMS verify during sign-in functionality

Code above runs the service for signing in and sending the SMS for verification code. Now, users need a screen to enter the SMS code. We have already created the endpoint and designed the service for this case. We need to send a request to that particular endpoint with **code**, **phone** **number,** and **userId**.

Here is the code for that:
{% gist https://gist.github.com/mertyerekapan/e7506f70649408d9e9c609b94d86c541.js %}
## Conclusion

This article covered adding the two-factor authentication method to our email authentication app using [**Next.js**](https://nextjs.org/), [**Twilio**](https://twilio.com/), and [**Altogic Client Library**](https://clientapi.altogic.com/v1.3.1/modules.html). Thanks to [**Altogic**](https://altogic.com/), we can build this functionality with just a few lines of code.

You can check out the [GitHub repository](https://github.com/altogic/altogic/tree/main/examples/nextjs-two-factor-authentication) for other functionalities and the rest of the code. You can also clone it and build your app on top of it.