Introduction
SMS OTP (one-time password) is a feature that allows login to an account via SMS without having to use any username and password. This saves time as there is no need to retype the credentials again every time you log in. An OTP is usually used to verify existing users, by which means the user must send back the obtained verification code to the server before being allowed to enter the system.
Due to stronger account protection, OTP is widely used in various systems such as e-commerce, m-banking, etc. That is, when we register or login to a system, we must enter the OTP code sent to our number.

From the explanation above, you must think that it is very difficult to apply OTP to the system because we have to deal with providers and also have to understand how authentication works. even though we can outsmart it with the help of Supabase, which provides the ability to generate OTP, which will later be integrated with Twilio.
SMS OTP Concept
Knowing how SMS OTP works is necessary to comprehend what we will learn this time.

It can be seen that supabase is used to generate OTP, then twilio is assigned to send the OTP code to the destination number. After the user gets the OTP code, the user can send the OTP code for verification.
Setup Twilio
First of all, you need to sign up for a free trial account using this link. Twilio | Try Twilio Free | www.twilio.com
We will be redirected to the console page to create a project after logging in.

You can type whatever you like for the project's name.

To make sure we were really human, Twilio asked for a phone number confirmation.

Twilio will ask several questions regarding the type of project to be created. We can fill out the form as in the example below.

The next step is to create a virtual number that will be used to send OTP to users later on.

In the Account Info
section, there are fields for SID, token, and phone number. This is what we will use later.

Testing Twilio SMS with curl
We can use curl to try to send SMS from the virtual number by replacing the SID
, body
, from
, to
, and token
with your own.
curl -X POST https://api.twilio.com/2010-04-01/Accounts/[YOUR_SID]/Messages.json \
--data-urlencode "Body=Hello from jagad.dev" \
--data-urlencode "From=[YOUR VIRTUAL NUMBER]" \
--data-urlencode "To=[YOUR NUMBER]" \
-u [YOUR_SID]:[YOUR_TWILIO_AUTH_TOKEN]
It can be seen that the SMS went to the destination number after the curl is executed.

Setup Supabase
In this section, you need to register for Supabase, which will then be integrated with Twilio. You can register here
After that, go to the authentication section where we will find settings related to auth providers (phone provider).

In the phone provider section, we will be asked to enter the SMS provider, which we will fill in with Twilio along with the sid, token, and phone number of the Twilio that we created earlier.

We also need API keys, which will be used to access the database via URL.

Login via OTP with Supabse
We must install Supabase in order to log in using OTP.
# npm
npm install @supabase/supabase-js
# or
# yarn
yarn add @supabase/supabase-js
After that, we configure the supabase by changing the url and key to the url and key from the Supabase that you have.
const { createClient } = require("@supabase/supabase-js");
// create client
const supabase = createClient(
"YOUR_SUPABASE_URL",
"YOUR_SUPABASE_KEYS"
);
Create a function to generate an OTP code which will later be sent by Twilio to the user's number.
const { createClient } = require("@supabase/supabase-js");
// create client
const supabase = createClient(
"YOUR_SUPABASE_URL",
"YOUR_SUPABASE_KEYS"
);
// login via otp
const loginOTP = async (phone) => {
let { user, error } = await supabase.auth.signIn({
phone,
});
return error;
};
// The user number to which the OTP code will be sent
loginOTP("+628674563332")
After running, the OTP code will be sent to the user number.

Verify SMS OTP
To check whether the OTP entered by the user is valid, it must be verified by the system.
const { createClient } = require("@supabase/supabase-js");
// create client
const supabase = createClient("YOUR_SUPABASE_URL", "YOUR_SUPABASE_KEYS");
// Verify SMS OTP
const verifyOTP = async (phone, code) => {
let { session, error } = await supabase.auth.verifyOTP({
phone,
token: code,
});
return { session, error };
};
// the user number + OTP code
verifyOTP("+628674563332", 938493);
When the user enters the wrong OTP, it will give a message that the OTP is invalid.
{
session: null,
error: { message: 'Token has expired or is invalid', status: 401 }
}
When the user enters the OTP correctly, it will return a session.
{
session: {
access_token: 'USER_TOKEN',
token_type: 'bearer',
expires_in: 3600,
refresh_token: 'USER_REFRESH_TOKEN',
user: {
id: '',
aud: 'authenticated',
role: 'authenticated',
email: '',
phone: '08488393343',
phone_confirmed_at: '2022-08-13T07:47:12.008645028Z',
confirmation_sent_at: '2022-08-13T07:46:39.584682Z',
confirmed_at: '2022-07-07T05:42:18.509965Z',
last_sign_in_at: '2022-08-13T07:47:12.009974864Z',
app_metadata: [Object],
user_metadata: {},
identities: [Array],
created_at: '2022-07-07T05:22:11.119149Z',
updated_at: '2022-08-13T07:47:12.011685Z'
},
expires_at: 1660380427
},
error: null
}
Implementation with Next.js
Clone the repository I've created.
rename .env.example
to .env.local
and put the supabase url and key in that file.
NEXT_PUBLIC_SUPABASE_URL=PUT_HERE
NEXT_PUBLIC_SUPABASE_ANON_KEY=PUT_HERE
Install the library in package.json
with the following command:
# npm
npm install
# or
# yarn
yarn install
Run the project with the following command:
# npm
npm run dev
# or
# yarn
yarn dev
Here is a video implementation of SMS OTP using Next. Js
Conclusion
Creating an OTP SMS is quite simple, but the simplicity is due to dependence on third parties such as Supabase and Twilio.
The best approach, in my opinion, is to first rely on a third party if the application we are building is really still small.