How to set up Vonage in Appwrite
Tags: appwrite, vonage, authentication
Published: 2023-09-07 17:37:22

Appwrite, as a backend-as-a-service, provides phone authentication where users can create accounts and log in using SMS. Appwrite requires an SMS provider to be set up for this to work. One such SMS provider is [Vonage](https://www.vonage.com/?utm_source=hackmamba&utm_medium=hackmamba-blog).

In this tutorial, we will learn how to set up a Vonage account, configure it to be used with [Appwrite](https://appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog), and build a Next.js app to put it all together.

## GitHub

Check out the source code [here](https://github.com/obinnadtq/appwrite-vonage).

## Prerequisites

To follow along in this tutorial, we require the following:

- A basic understanding of JavaScript
- Familiarity with [Next.js](https://nextjs.org/)
- [Docker](https://www.docker.com/get-started/)

## New to Appwrite?

[Appwrite](https://appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog) is an open-source backend-as-a-service that abstracts all the complexity of building applications by providing a set of APIs for core backend needs. Appwrite does a lot of heavy lifting for developers by providing authentication, database, file storage, functions, webhooks, and much more.

## What is Vonage?

[Vonage](https://www.vonage.com/?utm_source=hackmamba&utm_medium=hackmamba-blog) provides APIs that help organizations enhance customer experience by scaling to best meet their needs. They provide several communication channels like Voice, Video, SMS, MMS, and social chat apps like Facebook, Whatsapp, and Viber, which businesses can use to reach and engage customers.

In this tutorial, we will use the SMS API integrated with Appwrite for phone authentication.

## Setting up Vonage

We’ll first need to create a Vonage account. To create an account, head over to Vonage’s [website](https://www.vonage.com/?utm_source=hackmamba&utm_medium=hackmamba-blog) to [signup](https://ui.idp.vonage.com/ui/auth/registration?utm_source=hackmamba&utm_medium=hackmamba-blog) to use the Communication APIs. The signup page looks like this:

![Vonage signup page](https://paper-attachments.dropboxusercontent.com/s_D7115481C6AE631FCC16EFA49901E87291B2E979E0D7278BFD5E3883AA00BEC9_1690654335204_Screenshot+2023-07-29+at+20.10.45.png)


After signing up, the Vonage API dashboard is displayed.

![Vonage dashboard](https://paper-attachments.dropboxusercontent.com/s_D7115481C6AE631FCC16EFA49901E87291B2E979E0D7278BFD5E3883AA00BEC9_1692217600822_image.png)


We can send SMS, make voice calls and perform other functions from the dashboard. We can also see the **API key** and **API Secret** on the dashboard. We will keep them handy as we need them in the next step.

## Installing Appwrite

We need to have an Appwrite server running locally on our system. We can set it up [locally](https://appwrite.io/docs/self-hosting#installWithDocker) or using any of the [one-click setups.](https://appwrite.io/docs/self-hosting#one-click-setups) To set it up locally, run the command below:
```powershell
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:1.3.8
```

The command installs Appwrite on our local machine. We will use the default configurations provided. An `appwrite` folder is created that contains a `docker-compose.yml` and `.env` file. 

Once the installation is complete, we will update two environment variables in the `.env` file. The environment variables are `_APP_SMS_PROVIDER` and `_APP_SMS_FROM`. 
`_APP_SMS_PROVIDER` is a connection string that helps Appwrite connect to the Vonage API, and `_APP_SMS_FROM` is our Vonage phone number or brand name.
```powershell
_APP_SMS_PROVIDER=phone://[API KEY]:[API SECRET]@vonage
_APP_SMS_FROM=<YOUR PHONE NUMBER OR BRAND NAME>
```

After updating the environment variables, we will restart our Appwrite server for the changes to take effect. To restart the server, we will run the command below from the `appwrite`  folder that was created during installation.
```powershell
docker compose up -d
```

Then, we will navigate to `http://localhost` to sign up/sign in to our Appwrite account.

![Appwrite signup page](https://paper-attachments.dropboxusercontent.com/s_D7115481C6AE631FCC16EFA49901E87291B2E979E0D7278BFD5E3883AA00BEC9_1690661827858_image.png)


Next, we will create a new project. We will name our project `Appwrite-Vonage`

![Creating an Appwrite project](https://paper-attachments.dropboxusercontent.com/s_D7115481C6AE631FCC16EFA49901E87291B2E979E0D7278BFD5E3883AA00BEC9_1691088730332_image.png)


After the creation of the project, we will copy the `Project ID` and `API Endpoint` from the Settings tab, as we will need them in the next step.

![Fetching Appwrite project credentials](https://paper-attachments.dropboxusercontent.com/s_D7115481C6AE631FCC16EFA49901E87291B2E979E0D7278BFD5E3883AA00BEC9_1691088763754_image.png)

## Setting up our Next.js project

We need to create a Next.js project to see the phone authentication in action. Open the terminal and enter the following command to scaffold a Next.js project.
```powershell
npx create-next-app phone-authentication
```

We will have a series of prompts

![Creating a Next.js application](https://paper-attachments.dropboxusercontent.com/s_D7115481C6AE631FCC16EFA49901E87291B2E979E0D7278BFD5E3883AA00BEC9_1691849659608_image.png)


Next, we will go to the project directory and start the development server on `localhost:3000` with the commands below.
```powershell
cd phone-authentication && npm run dev
```

To use Appwrite in our application, we will install the Appwrite client-side SDK for web applications using the command:
```powershell
npm install appwrite
```

Next, we will create a `.env.local` file in our project root for our environment variables. We will add the following entries to our `.env.local` file.
```
PROJECT_ID=<APPWRITE_PROJECT_ID>
ENDPOINT=<APPWRITE_ENDPOINT>
```

The values of the environment variables were obtained in the previous step when we created our Appwrite project. To access the environment variables within our application, we will modify the `next.config.js` file. The file should look like this.
```javascript
/** @type {import('next').NextConfig} */
const nextConfig = {
    env: {
        PROJECT_ID: process.env.PROJECT_ID,
        ENDPOINT: process.env.ENDPOINT
    }
}
module.exports = nextConfig
```  
    
## Setting up the Appwrite SDK

We will create our Appwrite service that will help us abstract all the SDK calls. Create a file `src/appwrite.js` and fill it in with the following content.
```javascript
import { Client, Account } from 'appwrite';

const client = new Client();

client
    .setEndpoint(process.env.ENDPOINT)
    .setProject(process.env.PROJECT_ID);

const account = new Account(client);

export const getAccount = async () => account.get();

export const createPhoneSession = async (number) => account.createPhoneSession('unique()', number);

export const updatePhoneSession = async (userId, secret) => account.updatePhoneSession(userId, secret);

export const deleteSession = async () => account.deleteSession('current');
```   

The code above imports the **Client** and **Account** objects from Appwrite. Then, an instance of the **Client** object is created. We then set our `Endpoint` and `Project ID` that we obtained from the previous step into our client instance. Next, an instance of the **Account** object is also created.

We have created four different functions that return methods of the `account` instance. The methods are:

- `getAccount` : gets the current logged-in user account.
- `createPhoneSession`: creates a new phone session by sending an SMS with a secret key for creating a session. This is where we will see our Vonage SMS API action.
- `updatePhoneSession`: completes the creation of the phone session by using the code sent via SMS and the **userId** gotten from the `createPhoneSession` function.
- `deleteSession` : deletes a current session by logging out the user.

We will see these functions in action when we start building our UI in the next section.

## Building our user interface

Our UI will consist of two pages, one for the home page and the other for the login.
First, we will modify the file `src/app/page.js``,` which is our home page. The file should look like this
```javascript
'use client';

import { getAccount, deleteSession } from '@/appwrite';
import React, {useEffect} from 'react';
import { useRouter } from 'next/navigation';

export default function Home() {
  const router = useRouter();

  useEffect(() => {
    (async() => {
      try{
        await getAccount();
      }
      catch(e){
        console.log(e);
        router.push('/login');
      }
    })()
  }, []);

  const logout = async () => {
    try {
      await deleteSession();
      router.push('/login');
    } catch (e) {
      console.log(e);
    }
  };

  return (
    <div style={{textAlign: "center"}}>
      <h1>Welcome</h1>
      <button onClick={logout}>Logout</button>
    </div>
  )
}
```    
    

The code above tries to fetch the user account details from Appwrite using the `getAccount` function in our `src/appwrite.js` file. If the user is not found, an exception is thrown and then caught in the catch block, and the user is redirected to the login page. There is also a logout button that deletes the current session and redirects us to the login page.

Next, we will create a file `src/components/SignupForm.js`, our signup form component. The content of the file should look like this.
```javascript
'use client';

import { createPhoneSession } from "@/appwrite";
import React, { useState } from "react";
import VerificationForm from "./VerificationForm";

const SignupForm = () => {
  const [phoneNumber, setPhoneNumber] = useState("");
  const [isVerificationSent, setIsVerificationSent] = useState(false);
  const [userId, setUserId] = useState("");

  const handlePhoneNumberChange = (event) => {
    setPhoneNumber(event.target.value);
  }

  const handleSubmit = (event) => {
    try {
      const response = createPhoneSession(phoneNumber);
      response.then(user => {
        setUserId(user['userId'])
      })
      event.preventDefault();
      alert("verification code has been sent");
      setTimeout(() => {
        setIsVerificationSent(true);
      }, "1000");
    }
    catch (e) {
      console.log("error while creating phone session", e);
    }
  }

  return (
    <>
      {!isVerificationSent && (
        <form onSubmit={handleSubmit}>
          <div>
            <label style={{ marginRight: "10px" }}>
              Phone Number:
            </label>
            <input type="text" name="phoneNumber" value={phoneNumber} onChange={handlePhoneNumberChange} style={{ width: "150px" }} required />
          </div>
          <div style={{ textAlign: "center", marginTop: "20px" }}>
            <input type="submit" value="Get Code" style={{ width: "100px" }} />
          </div>
        </form>
      )}
      {isVerificationSent && (
        <VerificationForm userId={userId}/>
      )}
    </>
  )
}

export default SignupForm;
```    
 
The code above does the following:

- Creates a form for inputting the phone number for verification. 
- Then we use the React hook `useState` to manage the state of the phone number and whether a verification code has been sent. 
- When `Get Code` button is clicked after inputting the phone number, we create a phone session using the `createPhoneSession` function and send a verification code to the phone number. If the verification code is sent successfully, the `VerificationForm` component is displayed. 
- Then, the `userId` property is passed from the response of the `createPhoneSession` function as a props to the `VerificationForm` component.

Next, we will create a new component `src/component/verificationForm.js`, which is where we will input the verification code sent via SMS to our phone number. The file should look like this:

```javascript
'use client';

import { updatePhoneSession } from "@/appwrite";
import React, { useState } from "react";
import { useRouter } from 'next/navigation';

const VerificationForm = ({userId}) => {
  const [verificationCode, setVerificationCode] = useState("");
  const router = useRouter();

  const handleVerificationCodeChange = (event) => {
    setVerificationCode(event.target.value);
  };

  const handleSubmit = (event) => {
    try{
      updatePhoneSession(userId, verificationCode)
      router.push('/');
      event.preventDefault();
    }
    catch(e){
      console.log("error while updating phone session", e);
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label style={{ marginRight: "10px" }}>
          Verification Code:
        </label>
        <input type="text" name="verificationCode" value={verificationCode} onChange={handleVerificationCodeChange} style={{ width: "150px" }} required />
      </div>
      <div style={{ textAlign: "center", marginTop: "20px" }}>
        <input type="submit" value="Verify" style={{ width: "100px" }} />
      </div>
    </form>
  )
};

export default VerificationForm;
```

The code above creates a form where we will input our verification code. When the verification code is entered into the form, and the form is submitted, it calls the `updatePhoneSession` function that completes the sign in process. When we successfully sign in, we are redirected to the home page.

The video below shows a demo of the whole process. The phone number has been masked in the video.

{%vimeo https://vimeo.com/862109620?share=copy %}

We can also confirm from our Appwrite instance that the user was successfully logged in.

![Logged in user](https://paper-attachments.dropboxusercontent.com/s_D7115481C6AE631FCC16EFA49901E87291B2E979E0D7278BFD5E3883AA00BEC9_1691090996170_Screenshot+2023-08-03+at+20.56.31.png)

## Conclusion

In this tutorial, we learned how to set up phone authentication using Appwrite and Vonage. We introduced Vonage and the services they provide. We also looked at how to set up a Vonage account. We learned how to install an Appwrite server locally and change the environment variables needed for phone authentication. We built a simple Next.js application to tie everything together.

## Resources
- Vonage’s [website](https://www.vonage.com/?utm_source=hackmamba&utm_medium=hackmamba-blog)
- [Appwrite](https://appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog)
- [Installing an Appwrite instance locally](https://dev.to/hackmamba/create-a-local-appwrite-instance-in-3-steps-19n9?utm_source=hackmamba&utm_medium=hackmamba)