DEV Community

Cover image for How to build Phone Number-Based Authentication with React, Altogic and Twilio
yasinkuyuk for Altogic

Posted on • Edited on

How to build Phone Number-Based Authentication with React, Altogic and Twilio

Introduction

This article will cover phone number-based authentication basics using React and Altogic, a backend-as-a-service platform using it’s client library. You can checkout the Github repository.

So, what is phone number-based authentication?

Users can sign up for the application by providing their phone number and password only. This authentication method does not require users to specify their email addresses. Thus, users can log in to the application using their phone number and the password they set when signing up.

With phone number authentication, the application will send an SMS code to the user through Twilio. After users receive the SMS message from the provider, they can use this code to verify their phone number.

It is also possible to set up the authentication system through other providers such as MessageBird and Vonage.

In the rest of the article, I’ll explain how phone authentication works and set up phone number authentication to a Web application using the Altogic Client Library and React as a frontend.

YouTube Promo Video

How does Phone Number Based Authentication work?

Authentication with the Phone Number consists of a few steps:

  1. Users can enter their phone number and password on the Sign Up page.

  2. Then the system will send an SMS to the given phone number with Twilio.

  3. After the user enters the verification code in the SMS, the system completes the phone number verification.

  4. Users will be able to sign in 2 ways:

    • Sign in with credentials: Password and phone number
    • Sign in with One-Time Passwords(OTP), where OTP is sent as an SMS message

OTP: The automatically generated password authenticates the user for a single session.

Developers can either configure the validity period of the verification code or the user session duration.

How to Setup Phone Number Based Authentication with Altogic?

Creating App in Altogic

To enable phone number authentication, we need to create an app in Altogic.

We can create an app with the Altogic Designer really fast. To create an app via the Designer:

  1. Log in to Altogic with your credentials.

  2. Select New app.

  3. In the App name field, enter a name for the app.

  4. And click Create.

Creating App in Altogic

Here, you can customize your subdomain, but not necessarily to do, Altogic automatically creates one for you, which will be your envUrl. You don’t need to worry if you lost your envUrl; you can get it from the Environments view of Designer.

Getting the environment URL

After creating our app, we need envUrl and clientKey to access our app via Altogic Client Library to create a web application.

In order to get the clientKey we need to enter the app which we have created before and;

  1. Click on App Settings at the left-bottom of the designer.

  2. And click on Client library keys section.

Getting Client Library Key

We can create new clientKey from that page, but thanks to Altogic for creating one clientKey automatically for us, so let’s copy the existing clientKey from the list.

Really cool! Now everything is ready at the backend, time to continue Twilio Integration.

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 will use the free trial, you will need to take Twilio phone number to send SMS messages to the users.

  1. Create an Account in 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

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

  1. Click on the Explore Products in the left sidebar

    1. 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.

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 SidebarMessagingSettingsGeo permissions.

💡 After configuring the Twilio account, you have to enable the phone number and password based sign up from Designer → App Settings → Authentication → Mobile Phone Authentication → Enable phone number and password based sign up in Altogic client library.
Paste the Twilio Account SID,Twilio Authentication Token and Twilio Phone Number to the related fields.

Setting up Twilio with Altogic

Frontend Development

Installation

Before installing the application, be sure you have already installed NodeJS in your development environment.

To install

💡 You can visit: https://nodejs.org/en/download/ to download.

To get started, open the terminal and create a new React project

// creates a react app with the name of `altogic-react-phone-authentication-tutorial`
npx create-react-app altogic-react-phone-authentication-tutorial
Enter fullscreen mode Exit fullscreen mode

The above command creates a React project in the altogic-react-phone-authentication-tutorialdirectory.

cd altogic-react-phone-authentication-tutorial
touch .env
Enter fullscreen mode Exit fullscreen mode

Create a .env file in the root directory of your application, open the file in your editor and paste the following.



Replace YOUR-APPLICATION-ENV-URL and YOUR-APPLICATION-CLIENT-KEY with the envUrl and clientKey you copied before, then return to your terminal.

Install the Altogic Client Library to our project by using NPM or Yarn by running the following command:

// Installation of Altogic Client Library with NPM
npm i altogic
Enter fullscreen mode Exit fullscreen mode

Next, create a file to handle the Altogic services and client.

Go back to your root directory and follow the commands below:

cd src
mkdir helpers
cd helpers
touch altogic.js
Enter fullscreen mode Exit fullscreen mode

altogic.js will be created in the src/helpers directory. Open the file in your editor and paste the following.



The third parameter of createClient function signInRedirect handles the redirection to the Sign In page automatically when you have invalid session tokens or signed out. This is a beneficial feature for managing sessions in scenarios when you sign out from your mobile phone.

Building Main React Components

The next step is to create the components that we’ll need for our application,

  1. SignIn — A form component that allows the user to sign in.

  2. SignUp — A form component that allows the user to sign up.

  3. Verification — A form component that verifies phone number.

  4. Home — A component that displays whether or not authentication was successful.

  5. RequiresAuth A wrapper component that checks whether the user is authenticated before rendering a component; otherwise, it redirects the user to the signup/login page.

  6. RequiresNotAuth — A wrapper component that checks whether the user is not authenticated before rendering a component; otherwise, it redirects the user back to the profile page(for example Sign In page).

  7. App — The main application component. It renders all the views with their properties.

  8. Sessions — A table component that allows user to manage and view their sessions.

  9. Profile — A component that users can view and manage profile data.

switch to the root directory of your react application and run following commands:

cd src
mkdir pages
cd pages
touch SignIn.js SignUp.js Verification.js Home.js Sessions.js Profile.js
Enter fullscreen mode Exit fullscreen mode

Going back to src directory again, and creating ‘components’ directory. We will create ‘Routes’ directory under ‘components’ directory:

cd ..
mkdir components
cd components
mkdir Routes
cd Routes
touch RequiresAuth.js RequiresNotAuth.js
Enter fullscreen mode Exit fullscreen mode

This creates a pages directory with the components in the src directory. Your folder structure should look similar to the screenshot

We’ll be using React Context API to manage the user and session data, and pass them to the components rendered based on whether the user is authenticated or not. We’ll also be using React Router to handle routing.

Go back to your root directory and open the terminal:

cd src
mkdir context
cd context
touch AuthenticationContext.js ModalContext.js CounterContext.js
Enter fullscreen mode Exit fullscreen mode

To install React Router run the following command.

npm install react-router-dom
Enter fullscreen mode Exit fullscreen mode

We will use Tailwind CSS and Headless UI library for styling the project. Run the following commands in the root directory to install the library.

npm install -D tailwindcss postcss autoprefixer
npm install @headlessui/react
Enter fullscreen mode Exit fullscreen mode

Below command will create tailwind.config.js file:

npx tailwindcss init -p
Enter fullscreen mode Exit fullscreen mode

Open the tailwind.config.js in editor and copy/paste following script to configure template paths:



Open index.css file in src directory and add the following directives:



And we will use Font Awesome Icons in our project. You should install the Font Awesome Library to have well-looking components.

  1. Add SVG Core:
    npm i --save @fortawesome/fontawesome-svg-core
Enter fullscreen mode Exit fullscreen mode
  1. Add Icon Packages:
    npm i --save @fortawesome/free-solid-svg-icons
    npm i --save @fortawesome/free-regular-svg-icons
    npm i --save @fortawesome/free-brands-svg-icons
Enter fullscreen mode Exit fullscreen mode
  1. Add React Component
    npm i --save @fortawesome/react-fontawesome@latest
Enter fullscreen mode Exit fullscreen mode

Since we built a phone number-based authentication app, we will need a phone number input field. We will use react-phone-number-input library to increase UX.

npm i react-phone-number-input
Enter fullscreen mode Exit fullscreen mode

Finally all dependencies have been installed on our local machine. We can start our application by typing npm run start on the root directory. Let’s start coding!

Implementation

First of all, we will need some interface views and components such as;

  • Verification Phone number verification page

  • ResetPassword and ResetPasswordCode Sends users an SMS to reset their password

  • NotVerified Informs users that their phone number is not verified yet, and resends verification code

  • Counter Simple countdown timer for verification codes validity

  • Footer, Header, ProfileDropdown Navigation bar and footer badge

  • Notification Informs users about the responses

  • SessionTable and SessionItem for listing sessions

  • ChangeCredentials Tab structure to change view for ChangePhone and ChangePassword

  • PrimaryButton and SecondaryButton Custom buttons

Open your root directory and copy&paste lines one by one to create files.

cd src/components
touch Counter.js Footer.js Header.js Notification.js ProfileDropdown.js SessionItem.js SessionTable.js

mkdir Buttons
mkdir Profile

cd Buttons
touch PrimaryButton.js SecondaryButton.js

cd ../Profile
touch ChangeCredentials.js ChangePhone.js ChangePassword.js
Enter fullscreen mode Exit fullscreen mode

We will need two parent components that instruct routing rules to their child component. Rules mean,

  • Authenticated users are not able to view Sign Up and Sign In pages.

  • Unauthenticated users are not able to view Profile and Sessions pages.

Since we have restricted rules, We have designed special particular components that restrict the child components: RequiresNotAuth and RequiresAuth



RequiresNotAuth.js



App.js This will be main component of our application. All routes and views will be rendered in App component.



As you can see in the App.js component, we have three different Provider&Context structure:

  • AuthenticationProvider: Stores functions, states that are related with authentication, such as calling Altogic Client Library functions

  • ModalProvider: Manages push notification flow in the app

  • CounterProvider: Stores and handles the deadline of the verification code’s expiry date

Just for now, I am skipping the implementation of AuthenticationContext, we will have further been discussing “How to build context provider structure and how it works?”.

Since we built a phone number based authentication app; we need SignIn and SignUp components to handle form actions. I’ve excluded all the functions ,which works asynchronously because of the Altogic connections, to the Authentication Context to manage and access it easily from other components.

Let’s start coding the SignUp component first. We have a form structure to receive necessary data from the user. There is a button to handle the registration process at the bottom of the form structure. When you click this button, the signup() function is triggered, defined in the 23rd line. Here, we call context.signup() function defined in AuthenticationContext. Thus, Altogic functions stay together and stored in the context.


Sign Up page preview

We’ve entirely coded the sign up form. Now, we need a sign in form to sign users in.

We’ve developed signin() function -in line 24-, that will be triggered after the user clicks the button. Like with the SignUp component, context.signin() will be triggered inside the component’s own function.


Sign In page review

We have finished the implementation of the Sign Up and Sign In page. Since the users have to verify their phone number, we need to built a Verification component, which will take verification code as single parameter. When you click to the button, verify() defined inside the function, will be executed. In this function, we execute context.verifyPhoneNumber() function to verify our phone number with Altogic.


Verify Phone Number page preview

The common point of the three component SignIn, SignUp and Verification is; they three have buttons, functions and forms inside the component. Also, they also importing AuthenticationContext as context. I want to explain the simplified workflow of communications between components and contexts:

  1. User clicks the button Sign In, Sign Up, Verify

  2. Clicking triggers signin(), signup(), verify() function inside component

  3. context.signIn() function is called by handleClick()function

Authentication Context

Finally, we came to the Context API part. Before moving on to the coding section, I think going over the Altogic Client Library functions will be very helpful.

  • altogic.auth.signUpWithPhone(phoneNumber, password, name) → Takes 3 parameters (Name field is optional)

  • altogic.auth.signInWithPhone(phoneNumber, password) → Return user and session response if the credentials are correct

  • altogic.auth.signOut(token) → Kill the given token and sign out from the related session

  • altogic.auth.signOutAll() → Sign out from all session related with your account

  • altogic.auth.resendVerificationCode(phoneNumber) → Resend verification code to verify your phone number

  • altogic.auth.changePassword(newPassword, oldPassword) → Change password

  • altogic.auth.getAllSessions() → Get list of all active sessions with your account

  • altogic.auth.sendResetPwdCode(phoneNumber) → Send a verification code to your phone number if you forgot your password

  • altogic.auth.resetPwdWithCode(phoneNumber,code,password) → Reset your password

  • altogic.auth.changePhone(password, phoneNumber) → Change phone number function takes phone number and password as arguement

  • altogic.auth.verifyPhone(phoneNumber, code) → Verify phone number with your verification code that comes to your phone number

Here we came to the one of the core component and structure of app, AuthenticationContext created using useContext() hook. Context is used to generate shared data accessible across the component hierarchy without passing props to each component. For example, isAuth state stores the boolean value of is user authenticated or not. Almost every component must use the isAuth state to handle it’s internal functionalities. I could pass props to each component like parent to child. However it is not flexible and easy to use. I built an AuthenticationContext to handle and manage all the data and functionalities related with authentication.

I defined all my Altogic functions and related states in AuthenticationContext to distribute it to the child components.


BONUS: EXTRA FEATURES

You can find extra features in the shared repository. Also you can find more and more functions, database queries, etc. In fact all your needs to build a backend app.

  • Upload profile photo

  • Remove profile photo

  • Update credentials(phone number and password)

  • List all sessions

  • Sign out from other sessions

  • Sign out from all sessions

You can see the list of related Altogic functions with above features:


Conclusion

In this tutorial, we walked through how to secure and verify your users in a React app using Altogic, Twilio and Tailwind CSS. Phone number-based authentication is one of the standard authentication method in the sector. Additionally, as a full-stack developer, I have to say that building the backend of the phone number-based authentication apps becomes so confusing to handle with coding the backend and integrating the 3rd party SMS providers simultaneously. Altogic provides terrific services and functions to create a backend app for phone number authentication. As we experienced in the article, it took just a few lines of code to build a backend app.

This super powerful and easy-to-implement app should be a baseline for your phone number-based projects, and you would develop on it. You should check out the repository for the application we built on GitHub for further details.

Top comments (0)