Implement Two-Factor Authentication (2FA) in 30 Seconds with Twilio Verify

March 02, 2023
Written by
Reviewed by

Implement Two-Factor Authentication in 30 Seconds with Twilio Verify

Twilio Verify is a service that enables businesses to easily and securely validate users through various channels, including SMS, WhatsApp, voice, and email. It provides a simple and scalable way to add Two-factor Authentication (2FA) to any applications or services, helping to protect against fraud and unauthorized access.

In this tutorial you will prototype a complete 2FA implementation in four quick steps. Once you learn how everything works you’ll be well on your way to incorporate 2FA into your application.

Requirements

To complete this tutorial you will need a Twilio account. If you are new to Twilio, click here to create a free account. Besides the account, all you need to complete this tutorial is a web browser and the curl command line utility.

Step 1: Create a Twilio Verify service

The first step is to create an instance of Twilio Verify in your account. To do this, open the Twilio Verify dashboard in your browser and click the “Create new” button.

Enter a friendly name for your Verify service such as My Verify Service, and then enable the channels that you’d like to use. In this tutorial you will be able to test the SMS, WhatsApp, and Voice channels.

Create a new Twilio Verify service

Click “Continue”. If you enabled SMS, you will now be asked about the Fraud Guard feature, which protects you against unwanted charges to your account due to fraud.

Enable Fraud Guard

Select “Yes” and click “Continue” to create your Verify service.

Step 2: Configure your credentials

In this step, you will gather three account credentials that are needed to use the Verify service. These will be installed as environment variables in a terminal session.

The first one is the “Service SID” that was assigned to the Twilio Verify service you created in Step 1. This is displayed in the “Service Settings” page you were redirected to after creating the Verify service.

Click the “Copy” button to the right of the Service SID. Then open your terminal window and set an environment variable with this code. If you are using a bash or zsh prompt, this is how to do it:

export VERIFY_SERVICE_SID=<paste-your-service-sid-here>

If you are using a different shell, you will need to adapt the above statement. We have a dedicated tutorial on setting environment variables that you can consult if you need help with this.

You can find the other two credentials in the main dashboard of the Twilio Console. Find the “Account Info” section and copy the “Account SID” and “Auth Token” codes to environment variables as shown below:

export TWILIO_ACCOUNT_SID=<paste-your-account-sid-here>
export TWILIO_AUTH_TOKEN=<paste-your-auth-token-here>

Step 3: Send a verification code

And now we get to the fun part. In this step you are going to send a verification code to your personal cell phone. With Twilio Verify this is done with a single API call that is so simple that it can be issued from the terminal using curl.

For a real-world application you can implement the same HTTP request using any HTTP client of your choice. If you prefer, you can also use the Twilio server-side helper library for your programming language of choice.

Send a verification code to yourself using this command:

curl -X POST https://verify.twilio.com/v2/Services/$VERIFY_SERVICE_SID/Verifications --data-urlencode "To=<your-phone-number>" --data-url "Channel=sms" -u $TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN

For complete details about the verification endpoint used here see the documentation.

This command uses the environment variables you defined in Step 2, so make sure you run it in the same terminal where those variables were entered. The request has two input variables called To and Channel, which you can see next to the --data-urlencode options. For the To variable you have to enter your cellular phone number in E.164 format.

For example, for a number based in the US the format is +1AAABBBCCCC, with AAA being the area code and BBB-CCCC the local number.

For the Channel variable there are a few options:

  • sms to issue the code via SMS
  • call to issue the code via voice call
  • whatsapp to issue the code via WhatsApp message
  • email to issue the code via email (note that this requires additional configuration of a SendGrid account)

The response from this request is a JSON structure that after formatting looks like this:

{
   "status":"pending",
   "payee":null,
   "date_updated":"2023-03-01T12:08:48Z",
   "send_code_attempts":[
      {
         "attempt_sid":"VL****************",
         "channel":"sms",
         "time":"2023-03-01T12:08:48.462Z"
      }
   ],
   "account_sid":"AC****************",
   "to":"+19999999999",
   "amount":null,
   "valid":false,
   "lookup":{
      "carrier":null
   },
   "url":"https://verify.twilio.com/v2/Services/VA****************/Verifications/VE****************",
   "sid":"VE****************",
   "date_created":"2023-03-01T12:08:48Z",
   "service_sid":"VA****************",
   "channel":"sms"
}

The most important field in this response is status, which should be returned as pending for a successful call.

A few moments after you run the curl command, you will receive a verification code through your selected channel.

Step 4: Verify a code

The final step is to verify that a code provided by the user is correct. This is done with the HTTP request that you see below:

curl -X POST https://verify.twilio.com/v2/Services/$VERIFY_SERVICE_SID/VerificationCheck --data-urlencode "To=<your-phone-number>" --data-url "Code=<your-verification-code>" -u $TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN

For complete details about the verification check endpoint used above see the documentation.

This request uses the same three credentials, and also has two variables. The To variable must have the same value that was used when requesting a code to be sent out. The Code variable must include the code that the user provided as verification.

When the verification succeeds, the following response is returned:

{
   "status":"approved",
   "payee":null,
   "date_updated":"2023-03-01T12:10:52Z",
   "account_sid":"AC****************",
   "to":"+19999999999",
   "amount":null,
   "valid":true,
   "sid":"VE****************",
   "date_created":"2023-03-01T12:08:48Z",
   "service_sid":"VA****************",
   "channel":"sms"
}

The important value to check from this response is status, once again, which should now be set to approved to indicate that the validation was successful.

If the code that is entered is incorrect, the response that is returned is this:

{
   "status":"pending",
   "payee":null,
   "date_updated":"2023-03-01T12:11:27Z",
   "account_sid":"AC****************",
   "to":"+19999999999",
   "amount":null,
   "valid":false,
   "sid":"VE****************",
   "date_created":"2023-03-01T12:11:19Z",
   "service_sid":"VA****************",
   "channel":"sms"
}

Here you can see that the status variable remains set to pending. In this situation the user should be allowed another chance to type the code, as the error could have been due to a typing mistake.

Conclusion

So there you have it, a complete 2FA flow implemented in four short steps. My hope is that with this gentle introduction you will be able to add 2FA support to your application without trouble.

If you’d like to learn more about Twilio Verify, the official documentation is the best resource. In addition to the traditional 2FA implementation demonstrated in this article you will learn about other more advanced solutions such as:

  • TOTP standard soft-tokens generated by Authy, Google Authenticator and other apps
  • Push verifications on iOS, Android, web and desktop apps
  • Silent device approval

I’d love to see what you build with Twilio Verify!

Miguel Grinberg is a Principal Software Engineer for Technical Content at Twilio. Reach out to him at mgrinberg [at] twilio [dot] com if you have a cool project you’d like to share on this blog!