Phone Authentication with Appwrite and Twilio
Tags: webdev, javascript, programming, tutorial
Published: 2022-06-29 14:28:58

Appwrite 0.15 was just announced and brings with it one of the most anticipated Appwrite features! Yes, you guessed that right! We’re introducing **phone authentication in Appwrite!** With this release you’ll now be able to authenticate users using their phone numbers. This release also introduces 3 new phone providers including **Twilio**, **TextMagic** & **TeleSign**!

![Built App](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s3p8isoccuq8n8ie08xw.png)
 
In this tutorial we’ll learn how to set up a **Twilio** account and configure it for use with Appwrite and build a Svelte app to put it all together! The app will demonstrate the usage of all the new phone authentication endpoints introduced in **Appwrite 0.15!** Here's what we will learn:
- To create sessions using a phone number and verify them. 
- To update a user’s phone number, send verification codes and update the verification status. 

Without further ado, let’s get started!


#### 🤔 New to Appwrite?
> [Appwrite](http://appwrite.io/) is an open-source back-end-as-a-service that abstracts all the complexity of building a modern application by providing you with a set of REST and Realtime APIs for your core back-end needs. Appwrite takes the heavy lifting for developers and handles user authentication and authorization, databases, file storage, cloud functions, webhooks, and much more!

## 🧑‍💻 Setting up Twilio

The first step is to create a Twilio account. Head over to the [Sign Up page](https://www.twilio.com/try-twilio), fill in your details, verify your email and phone number. On the Twilio Dashboard, click on the **Get a Twilio phone number** button.

![Twilio Dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/isd8qzj5no1nx78r65e1.png)
 
This generates a phone number that we can use to send messages from. Under the Account Info section, you’ll find the **Account SID**, **Auth Token** and the newly generated phone number. Keep these handy as you’ll need them in the next step.
 
There’s one last thing that we need to do in the Dashboard before we move to the next step. Since we’re using Twilio’s free trial, we can only send an SMS to verified phone numbers. Head over to the [Verified Callers IDs](https://console.twilio.com/us1/develop/phone-numbers/manage/verified) page and enter the numbers that you’d like to send messages to.

## ⚙️ Install Appwrite

Next, we need to get an Appwrite server up and running. You can either choose to [install it locally](https://appwrite.io/docs/installation#installWithDocker) on your system or deploy it on the cloud with one of our [one click setups](https://appwrite.io/docs/installation#one-click-setups).

TLDR; It only takes a single magic command! 😊 

```bash
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:0.15.1
```

This command installs Appwrite and creates an **appwrite** folder with **docker-compose.yml** and **.env** files. Once the installation is complete, head over to the **appwrite** folder. 

We need to update two variables in the **.env** file namely **_APP_PHONE_PROVIDER** and **_APP_PHONE_FROM**. **_APP_PHONE_FROM** is the phone number you just obtained from Twilio and **_APP_PHONE_PROVIDER** is a DSN string that helps Appwrite connect to the Twilio API.

**_APP_PHONE_PROVIDER** takes the following format

```bash
_APP_PHONE_PROVIDER=phone://<Account SID>:<Auth Token>@twilio
```

**_APP_PHONE_FROM** takes the following format

```bash
_APP_PHONE_FROM=+14344251928
```

![Account Info](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/avctf0wwvj14o27873bm.png)

You can obtain the **Account SID**, **Auth Token** and the phone number from the Account Info section of the Twilio Dashboard.

Once that is done, we need to restart the Appwrite server for the environment variables to take effect. Please note that this command needs to be executed from the **appwrite** folder that was created during installation.

```bash
docker compose up -d --force-recreate
```

Next, head over to **localhost** ( or your public IP address ) and create a new user account followed by a project with a name of your choosing.

![Appwrite create user](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5qz9r9jobl1h448rgusf.png)

![Appwrite Project Dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1zf94zqooxr4a4iyjsel.png)
 
Copy the **projectId** and the **endpoint** from the **Settings** page as we’ll need it for the web app we build in the next step!

## 🔮 Setting up Our SvelteKit Project

For the sake of this example, we’ll be using **SvelteKit** but the concepts and code examples remain true for all frameworks out there. First, we’ll need to create a new SvelteKit project and set up **Tailwind CSS**. I’ve found the official [Tailwind installation guide](https://tailwindcss.com/docs/guides/sveltekit) to be extremely helpful here. 

Instead of re-inventing the wheel here, I’d recommend you to complete the setup and return back to this tutorial. 

Alright! It’s time to install some of our dependencies! We’ll be using two dependencies for our project. Head over to the project folder and install them with the following commands

```bash
npm i -D @zerodevx/svelte-toast
npm i appwrite
```

Next, add the following entries into your .env file. You might need to create this file if it does not exist already.

```bash
VITE_APPWRITE_ENDPOINT=http://localhost/v1
VITE_APPWRITE_PROJECT_ID=<YOUR_PROJECT_ID]
```
Don’t forget to replace the values with your own Appwrite **projectId** and **endpoint** that you obtained from the Dashboard earlier.

## 🔨 Setting up the Appwrite SDK

Next, let’s create our Appwrite service that will help abstract all the SDK calls to a single place. Create a new file `src/lib/appwrite.ts` and fill in the following contents

```ts
import { Client, Account } from 'appwrite';

const client = new Client();

client
    .setEndpoint(import.meta.env.VITE_APPWRITE_ENDPOINT)
    .setProject(import.meta.env.VITE_APPWRITE_PROJECT_ID);

const account = new Account(client);

export class AppwriteService {
    public static async getAccount(): Promise<any> {
        return account.get();
    }

    public static async createAccount(email: string, password: string, name?: string): Promise<any> {
        return account.create('unique()', email, password, name);
    }

    public static async createEmailSession(email: string, password: string): Promise<any> {
        return account.createEmailSession(email, password);
    }

    public static async deleteSession(): Promise<any> {
        return account.deleteSession('current');
    }

    /** Phone Authentication endpoints */
    public static async createPhoneSession(number: string): Promise<any> {
        return account.createPhoneSession('unique()', number);
    }

    public static async updatePhoneSession(userId: string, secret: string): Promise<any> {
        return account.updatePhoneSession(userId, secret);
    }

    public static async updatePhone(number: string, password: string): Promise<any> {
        return account.updatePhone(number, password);
    }

    public static async createPhoneVerification(): Promise<any> {
        return account.createPhoneVerification();
    }

    public static async updatePhoneVerification(userId: string, secret: string): Promise<any> {
        return account.updatePhoneVerification(userId, secret);
    }
}
```

Here,  we import the appwrite SDK and initialize the **Client** and **Account** services. We also export an **AppwriteService** class with a lot of static methods that we can use across our app. The `appwrite.ts` file is all it takes to integrate Appwrite into the project. All the other files deal with the UI of the project and should be fairly straightforward to read and understand.

In order to keep this tutorial concise, we’ll just copy over the contents for all the other files from the completed [GitHub project](https://github.com/christyjacob4/appwrite-auth-demo). Here are a list of files we need to copy

* [Toast.ts](https://github.com/christyjacob4/appwrite-auth-demo/blob/main/src/lib/Toast.ts) - This file contains the theming configuration for our toast messages
* [__layout.svelte](https://github.com/christyjacob4/appwrite-auth-demo/blob/main/src/routes/__layout.svelte) - This file defines the base layout for all our screens
* [index.svelte](https://github.com/christyjacob4/appwrite-auth-demo/blob/main/src/routes/index.svelte) - UI for the user profile page
* [login.svelte](https://github.com/christyjacob4/appwrite-auth-demo/blob/main/src/routes/login.svelte) - UI for the login with email page
* [loginPhone.svelte](https://github.com/christyjacob4/appwrite-auth-demo/blob/main/src/routes/loginPhone.svelte) - UI for the login with phone page
* [signup.svelte](https://github.com/christyjacob4/appwrite-auth-demo/blob/main/src/routes/signup.svelte) - UI for the signup page

Once complete, we’re all ready to preview the project. Run the following command to run a local development server.

```bash
npm run dev
```

That brings us to the end of this tutorial! I hope this guide helped you set up phone authentication in your web app and above all, I hope you enjoyed learning something new! I had a lot of fun learning Svelte and building a web app for this tutorial and I can’t wait to build some more apps!

## 📚 Resources
If you’re stuck at any point during the tutorial, feel free to reach out for help in our [friendly discord channels](https://appwrite.io/discord) run by humans! If you like what we do at Appwrite, don’t forget to drop us a tiny star on GitHub 😉 Here are some great resources to help you get started. 

* [Appwrite Resource Showcase](https://github.com/appwrite/awesome-appwrite)
* [Svelte Documentation](https://svelte.dev/tutorial/basics) 
* [Appwrite Documentation](https://appwrite.io/docs)
* [Appwrite's GitHub](https://github.com/appwrite/appwrite)