Passwordless Authentication With PHP Using Twilio Verify

December 03, 2021
Written by
Elijah Asaolu
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by

Passwordless Authentication with PHP using Twilio Verify

Passwordless authentication refers to an authentication method that does not require a password or any other knowledge-based secret to log a user into a system. This method of authentication adopts the means of authorizing users by sending a unique, one-time code (OTP) or magic link to the user via email, push notification, or text message.

In this article, you'll learn how the infrastructure underlying passwordless authentication works, and create a small app that uses this authentication approach.

How it works

Most passwordless authentication implementations have a single entry point, i.e., a single page for both new users signing up and for existing users logging in to their accounts.

In a typical implementation, both new and existing users are asked to enter their mobile phone number during either registration or login. After verifying the mobile number, the system checks if the user is an existing one or a new one. If they're an existing user, they're redirected to their dashboard. If they're a new user, they're redirected to a different onboarding page to update their information.

Benefits

Some of the advantages of implementing passwordless authentication include:

  • Improved user experience: This mode of authentication relieves users of the need to fill out password and confirm password fields, resulting in an increase in signup rate. It also alleviates the challenge of users having to remember complex passwords that adhere to various security policies.
  • Better security: Most internet users used the same password for multiple accounts before — and even after — the introduction of password generators and password managers. Additionally, gaining access to a user's password gives an attacker access to all of their accounts. Because there is no password to hack, passwordless authentication prevents this.

Drawbacks

  • A single point of failure: Because it requires a verification medium (email, push notification, or text message), the user will be unable to access the system if they do not have access to one of these mediums.

Now that you have a basic understanding of how passwordless authentication works, let's create a sample application that demonstrates how it works.

Prerequisites

The following prerequisites are required to follow along with this tutorial:

  • A basic understanding of PHP.
  • PHP 7.4 with the mysqli extension installed and enabled.
  • Composer installed globally.
  • A MySQL database.
  • A Twilio account. If you are new to Twilio click here to create a free account and receive a $10 credit when you upgrade to a paid account.

Plain vanilla PHP is used in the tutorial so that you can focus on the principles being taught, and not get lost in a specific framework.

Create the database

The first required step is to download the sample-db.sql file from the project's GitHub repository and import it into your database. The file contains the DDL to create the database schema for the project, a table named users with fields for a user id, name, and mobile phone number.

If you are not familiar with creating a database in MySQL via an SQL file, read this tutorial.

Create the application

Next, create a project directory, named passwordless-authentication, and navigate into it by running the commands below.

mkdir passwordless-authentication
cd passwordless-authentication

Following that, you need to establish a connection to the database. To do this, in your editor or IDE create a new file named connection.php, and paste the following code into it.

<?php

$connection = new mysqli('localhost', 'root', '', 'sample-db');

Where:

  • "localhost" is the database hostname or IP address.
  • "root" is the database username.
  • "(empty string)" is the database password.
  • "sample-db" is the database name.

For the app frontend, create four new files in the project's root directory: verify.php, onboard.php, process-verify.php, and process-onboard.php. Below is a description of what each file does.

File

Description

onboard.php

Is responsible for the front-end of our app entry point.

process-onboard.php

Contains the logic to process the form submitted in onboard.php.

verify.php

This contains the page for the user to enter the OTP sent to their mobile phone.

process-verify.php

This contains the code to verify if the OTP sent to the user is correct, as well as other database operations.

Then, in onboard.php paste the code below.

<?php
require('./process-onboard.php')
?>
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Welcome Page</title>
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
      rel="stylesheet"
    />
  </head>

  <body>
    <div class="d-flex min-vh-100 justify-content-center align-items-center">
      <div class="shadow-sm mx-2 border rounded p-5">
        <h3>Welcome back, user!</h3>
        <form action="/onboard.php" method="POST">
          <div class="form-group">
            <label for="uinput" class="mt-3 mb-1 text-muted">
              Kindly, enter your mobile number to proceed.
            </label>
            <input id="uinput" type="text" name="phone" class="form-control" />
            <button name="submit" type="submit" class="btn btn-success mt-2 w-100">
              Continue
            </button>
          </div>
        </form>
      </div>
    </div>
  </body>
</html>

The code above is responsible for creating a basic form which will accept the user's phone number. It requires process-onboard.php, which was created earlier, as the code for processing the form and connecting to Twilio's Verify API will be added here.

With the first part of the code complete, start the application by running the command below.

php -S localhost -t .

Now, open http://localhost/onboard.php in your browser, where it should look like the following.

The app&#x27;s onboarding page

Setting up Twilio

The next step is to add code to process-onboard.php, which integrates with Twilio's Verify API. First, paste the code below into process-onboard.php.

<?php

require __DIR__ . '/vendor/autoload.php';

use Twilio\Rest\Client;

$sid = "ACCOUNT_SID";
$token = "AUTH_TOKEN";
$serviceId = "SERVICE_SID";

if (isset($_POST['submit'])) {
    $phone = $_POST['phone'];
    $twilio = new Client($sid, $token);
    $verification = $twilio->verify->v2->services($serviceId)
        ->verifications
        ->create($phone, "sms");
    if ($verification->status) {
        header("Location: verify.php?phone=$verification->to");
        exit();
    } else {
        echo 'Unable to send verification code';
    }
}

The code triggers when the user submits the form in onboard.php. It:

  • Initializes a new Twilio Client object with the provided credentials.
  • Sends a unique code to the user’s mobile number.
  • Redirects the user to verify.php where they will be able to enter the code received.

Next, retrieve your Twilio ACCOUNT SID and AUTH TOKEN from your Twilio dashboard, which you can see in the screenshot below. 

Retrieve your Twilio auth token and account SID from the Twilio Console dashboard

After copying them, paste them in place of ACCOUNT_SID and AUTH_TOKEN in onboard.php, respectively.

Next, you need to create a Twilio Verify service. To do that, head to the Twilio Verify Dashboard. There, click on the red plus (+) button. In the "Create new Service" popup that appears, give the service a friendly name, as in the screenshot below.

Create new Twilio Verify service with friendly name site-verify

After entering the friendly name, click on the red Create button to complete creation of the new service. You'll then be on the "General Settings" page where you can see the properties associated with your new Twilio Verify service. Copy the SERVICE SID value and paste it in place of SERVICE_SID in process-onboard.php.

Twilio Verify general settings page with service SID

And finally, you need to install the Twilio SDK to use the Twilio verify API for implementing passwordless authentication. To do this, run the command below in your terminal, in the root of the project directory.

composer require twilio/sdk

Next add the code below to verify.php, which contains a form for the user to enter the unique code they’d received earlier.

<?php
require './process-verify.php';

$phone = (isset($_GET['phone'])) ? $_GET['phone'] : '+000000';
?>
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Verify Page</title>
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
      rel="stylesheet"
    />
  </head>

  <body>
    <div class="d-flex min-vh-100 justify-content-center align-items-center">
      <div class="shadow-sm mx-2 border rounded p-5">
        <h3>Complete verification!</h3>
            <?php if (isset($alert)) { ?>
                <div class="alert alert-success mt-4"><?php echo $alert; ?></div>
            <?php } ?>
        <form action="#" method="POST">
          <div class="form-group">
            <label for="code" class="mt-3 mb-1 text-muted">
              A verification code has been sent to
              <b><?php echo $phone; ?></b>, <br />
              enter the code below to continue.
            </label>
            <input
              id="code"
              type="text"
              name="code"
              class="form-control"
              required
            />
            <input type="hidden" name="phone" value="<?php echo $phone; ?>" />
            <button
              type="submit"
              name="submit"
              class="btn btn-success mt-2 w-100"
            >
              Submit
            </button>
            <small class="d-block mt-3">
              <a href="onboard.php" class="text-muted">Wrong number?</a>
            </small>
          </div>
        </form>
      </div>
    </div>
  </body>
</html>

Finally, to verify the code entered by the user, update process-verify.php with the code below.

<?php

require __DIR__ . '/vendor/autoload.php';
require './connection.php';

use Twilio\Rest\Client;

$sid = "ACCOUNT_SID";
$token = "AUTH_TOKEN";
$serviceId = "SERVICE_SID";

$twilio = new Client($sid, $token);

if (isset($_POST['submit'])) {

    $vCode = $_POST['code'];
    $phone = $_POST['phone'];

    $verification_check = $twilio->verify->v2->services($serviceId)
        ->verificationChecks
        ->create(
            $vCode,
            ["to" => "+" . $phone]
        );
    if ($verification_check->status == 'approved') {
        // checks if the user already exist in db
        $query = "SELECT mobile FROM users WHERE mobile = $phone";
        $result = $connection->query($query);

        if ($result->num_rows > 0) {
            $alert = "Welcome back to your account!";
        } else {
            // add new user to db
            $insertQuery = "INSERT INTO users (mobile) VALUES ('$phone')";
            $insertResult = $connection->query($insertQuery);
            if ($insertResult) {
                $alert = "Welcome, new user!";
            }
        }
    } else {
          $alert = "Welcome, new user!";
    }
}

The code above checks if the code entered is correct and if a user with this mobile number already exists in the database. If so and they're a new user, then a record for them is inserted into the database and prints the message "Welcome, new user!". Alternatively, if a user with this mobile number already exists and they're an existing user, then "Welcome back to your account!" is printed.

Finally, if you enter your mobile number in onboard.php, you will be redirected to the verification page, where you are required to enter the code that was sent to your phone, which you can see in the screenshot below.

Confirmation of verification code having been sent

And if you enter the correct code, the following message should appear.

Welcome new user after verification is complete.

That's how to implement passwordless authentication with PHP using Twilio Verify

Throughout this tutorial, you learned how passwordless authentication works, as well as some of the benefits and drawbacks of using it. You also created a sample app that uses this authentication method.

The complete code for this tutorial is available on Github for your convenience.

Authors Bio

I am a software engineer and technical writer. When I'm not coding, I like to share my skills and experience with other developers by writing technical articles.