Improving user engagement and interaction in web applications is crucial, and seamless communication is key. In today's interconnected digital world, SMS is still a powerful way to reach users quickly and efficiently. Incorporating this strong communication tool into a web application powered by Appwrite is easy.
In this article, we will discover the process of authenticating users through their phone numbers with the help of Appwrite's phone authentication APIs and Telesign. Find the project repository here.
Technology Overview
Telesign is an identity and customer engagement solution that provides sets of APIs for registering and verifying users using SMS, Voice, and phone number intelligence.
Prerequisites
To fully grasp the concepts presented in this tutorial, the following are required:
- Basic understanding of JavaScript and React
- Docker installed
- Telesign account
Getting started
To create a Next.js starter project, we should first navigate to the desired directory and run the command below in our terminal.
npx create-next-app@latest setup-telesign-for-sms-in-appwrite && cd setup-telesign-for-sms-in-appwrite
After running the command, we will be prompted to answer sets of questions. We can do so as shown below:
Would you like to use TypeScript? <No>
Would you like to use ESLint? <No>
Would you like to use Tailwind CSS? <Yes>
Would you like to use `src/` directory? <Yes>
Would you like to use App Router? (recommended) <Yes>
Would you like to customize the default import alias? <Yes>
What import alias would you like configured? @/* <Press Enter>
The command creates a Next.js project called next_telesign
and navigates into the project directory.
Next, we need to add Appwrite as a dependency. To do this, run the command below:
npm install appwrite
Set up Telesign as an SMS provider
Let's begin by logging in to our Telesign portal and making sure to save the Customer ID
and API Keys.
Lastly, we need to create and verify a test number. Any number we configure and verify here can receive SMS. To do this, we need to navigate to the **Manage test numbers**
screen.
Click the **Add a Number**
button, input the required details, **Submit**
, and **Verify**
.
Configure and create a project on Appwrite
To get started, first, we need to create an Appwrite instance in a preferred directory by running the command below:
docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
--entrypoint="install" \
appwrite/appwrite:latest
On creation, we should see an appwrite
folder with two files.
Secondly, we need to add Telesign as an SMS provider by modifying the environment variables in the .env
file as shown below:
_APP_SMS_PROVIDER=sms://<REPLACE WITH CREDENTIAL ID>:<REPLACE WITH API KEYS>@telesign
_APP_SMS_FROM=<REPLACE WITH THE PHONE NUMBER WE USED IN WHEN VERIFYING TELESIGN>
We must also ensure that the API Key provided by Telesign is URL encoded because it contains non-alphanumeric characters. To do this, we can navigate to the URLEncoder online platform, paste our API key, click the Encode button, and then copy the resulting encoded format.
Lastly, we need to sync the changes we made on the .env
file with our Appwrite server. To do this, we must run the command below inside the appwrite
directory.
docker-compose up -d
Set up a project on Appwrite
To get started, we need to navigate to the specified hostname and port http://localhost:80
, log in, click the Create project button, input next_telesign
as the name, and then click **Create**
.
Appwrite + Telesign in Next.js
Let's begin by going to our project's main directory and creating a new folder named helper
. Inside this folder, create a file called utils.js
and insert the code snippet provided below:
import { Client, Account } from "appwrite";
//create client
const client = new Client();
client.setEndpoint("http://localhost/v1").setProject("REPLACE WITH PROJECT ID");
//create account
const account = new Account(client);
//authenticate user with phone number
export const phoneAuth = (phone_number) => {
return account.createPhoneSession("unique()", phone_number);
};
//validate phone session
export const validateSMS = (userID, secret) => {
return account.updatePhoneSession(userID, secret);
};
The snippet above does the following:
- Imports the required dependency.
- Uses the
Client
andAccount
class to set up an Appwrite instance by specifying the endpoint and corresponding project ID. - Creates a
phoneAuth
andvalidateSMS
function that uses thecreatePhoneSession
andupdatePhoneSession
methods to create a user and validate the user using the code sent via SMS, respectively.
Secondly, we need to update the page.js
file inside the app
directory to include states and methods required by our application.
"use client";
import Head from "next/head";
import { useState } from "react";
import { phoneAuth, validateSMS } from "../../helper/utils";
export default function Home() {
const [value, setValue] = useState({
phone: "",
otp: "",
});
const [user, setUser] = useState(null);
const [isPhoneVerify, setIsPhoneVerify] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const handleChange = (e) => {
setValue({ ...value, [e.target.name]: e.target.value });
};
const handleSubmit = (e) => {
e.preventDefault();
setIsLoading(true);
phoneAuth(value.phone)
.then((res) => {
setUser(res.userId);
setIsPhoneVerify(true);
setIsLoading(false);
})
.catch((e) => {
alert("Error getting phone session!", e);
setIsLoading(false);
});
};
const handleValidatePhone = (e) => {
e.preventDefault();
setIsLoading(true);
validateSMS(user, value.otp)
.then((res) => {
alert(
`User successfully verified using for user with ID ${res.userId}, country Code ${res.countryCode}, and expires on ${res.expire}`,
);
setIsLoading(false);
})
.catch((e) => {
alert("Error validating session!", e);
setIsLoading(false);
});
};
return (
<div className="w-screen h-screen bg-white">
//UI AND IMPLEMENTATION GOES HERE
</div>
);
}
The snippet above does the following:
- Imports the required dependencies
- Creates state properties to manage application state
- Creates a
handleChange
function to control inputs - Creates a
handleSubmit
function that uses thephoneAuth
function to create a user - Creates a
handleValidatePhone
function that uses thevalidateSMS
function to verify the created user using the secret key sent via SMS
Lastly, we need to update the UI to display forms for creating and verifying users dynamically.
//IMPORTS GOES HERE
export default function Home() {
//STATES AND METHOD GOES HERE
return (
<div className="w-screen h-screen bg-white">
<Head>
<title>Appwrite + Telesign </title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className="py-4 px-4 lg:py-10 lg:px-10 w-full">
<div className="flex justify-center mb-8">
<h1 className="text-2xl font-medium text-gray-700">
Appwrite + Telesign
</h1>
</div>
<section className="flex justify-center">
{isPhoneVerify ? (
<div className="px-4 py-2 border rounded-lg w-full lg:w-2/4">
<div className="border-b h-8 mb-4">
<h3 className="text-gray-700">Verify phone number</h3>
</div>
<form onSubmit={handleValidatePhone}>
<fieldset>
<label className="text-sm text-gray-400 mb-4 block">
OTP
</label>
<input
name="otp"
className="border w-full rounded-sm mb-6 p-2"
required
value={value.otp}
onChange={handleChange}
type="tel"
/>
</fieldset>
<button
className="text-sm text-white px-8 py-2 rounded-sm bg-blue-600 hover:bg-blue-700"
disabled={isLoading}
>
Validate OTP
</button>
</form>
</div>
) : (
<div className="px-4 py-2 border rounded-lg w-full lg:w-2/4">
<div className="border-b h-8 mb-4">
<h3 className="text-gray-700">
Authenticate with your phone number
</h3>
</div>
<form onSubmit={handleSubmit}>
<fieldset>
<label className="text-sm text-gray-400 mb-4 block">
Phone number
</label>
<input
name="phone"
className="border w-full rounded-sm mb-6 p-2"
required
value={value.phone}
onChange={handleChange}
type="tel"
/>
</fieldset>
<button
className="text-sm text-white px-8 py-2 rounded-sm bg-blue-600 hover:bg-blue-700"
disabled={isLoading}
>
Submit
</button>
</form>
</div>
)}
</section>
</main>
</div>
);
}
Now that we have completed that task, we may begin running a development server using the following command:
npm run dev
We should have something similar to what is shown below.
Conclusion
This post discussed how to set up phone authentication in Next.js using Appwrite and Telesign. With Appwrite, developers can save application development time by leveraging intuitive authentication APIs without the associated technical overheads.
These resources might also be helpful: