Menu

Expand
Rate this page:

Verification and two-factor authentication best practices

Verification is an essential first step in your online relationship with a user. By verifying that a new user is who they say they are, you can reduce spam and fraud on your site while ensuring the user's security.

Designing user verification involves more than just picking the right verification channel. Twilio has supported thousands of customers rolling out verification and two-factor authentication (2FA) implementations. This guide will provide recommendations for each step of the user verification process, from collecting phone numbers to account recovery.

These recommendations are written with the Twilio Verify API in mind but many will apply regardless of your verification provider.

If you're ready to start building, check out one of our Verify Quickstarts, available in a variety of programming languages for a variety of verification channels.

Understand the difference between verification and authentication

Verification and authentication are similar user experiences but have a few key differences in how you can design the user experience.

Verification happens when you first associate details with a customer account. This could be:

  • At sign up
  • When the user provides new contact information like an email address or phone number
  • When the user associates a new device or browser with their account

Authentication, including two-factor authentication (2FA) or multi-factor authentication (MFA) happens during ongoing customer interactions like:

  • At login
  • During checkout or when making high value transactions
  • On customer service calls
  • Account changes like resetting a password or updating an address

The Twilio Verify API can be used to both verify and authenticate user identities and can be used for all of these customer interactions.

​​Plan a user registration flow

Balance speed with security

Like every security solution, you want to make sure that the friction you're adding isn't going to prevent the user from achieving their goals, whether that's signing up for your service or completing a transaction.

Support multiple authentication channels

The Twilio Verify API supports:

Each channel has different benefits. For example, SMS has the highest end user adoption while TOTP is more secure and works offline. You might ask if email-based 2FA is a good idea (better than no 2FA!).

Most companies support several verification channels and then let their users decide. For example, GitHub supports TOTP, SMS, and security keys and offers even more options for account recovery.

Read more about tradeoffs between the different authentication channels supported by the Verify API.

Should I use the SMS channel?

SMS offers less security than TOTP or push authentications, but in many cases you should still leave it available as an authentication option. SMS support is built into all mobile phones and—without a separate application—tokens delivered by SMS will make it to your users. The user experience benefits of SMS still make it a popular choice for many companies. Learn more about why SMS 2FA isn't going away.

If the choice is between password-only authentication or password plus SMS, adding SMS is a clear winner.

Which channels are the most secure?

Push authentications are the most secure channel for 2FA because they are tied to a specific device and resistant to phishing. Push also offers the ability to deny an authentication request, which can be used to detect fraud.

Push authentications are also very convenient for your users. Instead of having to open a mobile application and navigate to your website's token, push authentications present an "Approve"/"Deny" dialog within easy reach. This can be embedded directly into your application with our SDKs so it doesn't require the user to download an additional app.

Time-based one-time passwords (TOTP) are also a strong choice that provide additional security compared to SMS.

Suggested account verification, security, and usage flow

For an example user registration flow with one time passcodes, smart retry logic, and voice channel fallback, check out this Code Exchange project.

Let your customers pick the authentication channels they want to use

Allow customers to set authentication preferences and store those preferences for subsequent logins. This is a great way to delight your users and reduce frustrations during the authentication process. For example, landline users will want a voice call instead of an SMS. You could store preferences in your user database or use a third-party service like Segment Personas.

These channels can also be used for backup and account recovery (more on this below).

Design your user experience for verification success

Display complete contact information for initial user verification

For phone or email verification use cases (as opposed to ongoing login or two-factor authentication), display the complete identifier in the interface so the user can detect any typos during the registration process. You can also introduce an intermediate step that asks the user to confirm the phone number before you send the OTP in order to catch mistakes.

one time passcode input field with message that shows complete phone number with option to edit.

Think internationally for phone verification

Building international support for telephone numbers includes separating country code and phone number input fields in your form fields and storing phone numbers in the standard E.164 format.

If you're sending OTPs to countries that require pre-registration of sender IDs, you'll need to complete this application. Learn more about international support for Alphanumeric Sender IDs.

Learn how to build international phone number input in HTML and JavaScript on the Twilio Blog.

Validate phone numbers before sending one-time passwords (OTPs)

This topic is covered in depth in our blog post on best practices for phone number validation during new user enrollment.

You can also use Twilio's Lookup API to build an allow list of country codes in order to filter sign ups to meet compliance requirements, reduce fraud, or otherwise control your onboarding pipeline.

gif showing international telephone input plugin transforming a valid number to E.164 format and detecting an invalid number

Here are a few additional resources on building phone number inputs and validating numbers at this stage:

  1. Quick Deploy: international telephone input (seen above)
  2. How to Validate Phone Number Input in HTML and JavaScript

Take advantage of HTML attributes to improve your users' 2FA experience

Look no further than the humble <input> element as a place to optimize the user experience. Learn more about how to design your HTML attributes to support autocomplete and more in this blog post.

Use smart retry logic for delivering OTPs

To prevent abuse (and impatient users!) we always recommend building retry buffers into verification workflows. This helps prevent:

  • Accidentally spamming a user with repeated text messages
  • Hitting API rate limits
  • Toll fraud or unnecessary spend

We suggest limiting verifications to 1 request / 30 seconds per phone number with exponential backoff. Learn more in the blog post about best practices for managing retry logic with SMS 2FA or check out this Code Exchange project with an example retry logic flow seen below.

SMS Verification input box with title Enter the code sent to your device and subtitle resend code in 4 seconds

Add account recovery options early

Think about what happens when a user no longer has access to an authentication channel like a forgotten password or lost phone. Register at least one additional way to authenticate a user at sign up so that you always have a backup. Common combinations include:

  • Password + email
  • Email + phone number
  • Authenticator app (TOTP) + backup codes
  • Push authentication + phone number

Then if you're supporting two-factor authentication (2FA), add a third channel. For more recommendations, watch this talk on designing customer account recovery in a 2FA world or check out the slides.

Plan for verification and authentication after sign up

Always verify each new contact method you're adding

Send a one-time password to a phone number or email address the first time a user provides it. This ensures that the user has control of the device or identity. For email, verifying a user's email address the first time they provide it is a best practice to reduce fraud, ensure deliverability, and maintain a good sending reputation. If the user is using your mobile application, register the device as a factor to be used for Verify Push.

Wait until the information has been verified to store it in your database. Alternatively, add a "verified" flag. This helps prevent typos or other unverified information from being connected to a user account.

If you don't care about verifying a piece of contact information, ask if you need to collect it at all.

Mask phone numbers or other PII for ongoing authentication

Once the phone number has been verified the first time, subsequent uses should mask the phone number in order to prevent leaking PII. Unlike during initial verification, there is no option to edit a phone number for ongoing authentication in the example below. We recommend exposing 3 or 4 numbers and masking the rest like +1 (5**) ***-**67 or ********567.

Input box with title Enter the code sent to your device and subtitle showing that an SMS verification was sent to a partially obscured phone number

Incentivize two-factor authentication (2FA)

Offering 2FA doesn't help secure your customers if they don't opt in to the feature. Incentives can help users who feel burdened by the security investment.

Learn more about how companies are incentivizing users to enable 2FA.

Use the Twilio Verify API for comprehensive verification support

The Verify API helps you quickly build trust with the users accessing your platform and focus on your business logic.

Explore customization options

Choose the right token length

The API supports token lengths between 4 and 10 digits with a default of 6 digits. Longer verification codes have more combinations and are harder to guess or brute force. The API has robust rate limits that counter brute forcing attempts of any token length size. You can change the token length in the Verify Service section of the Twilio Console.

Customize the verification message

The Verify API supports a standard template. The English example is:

Your <App Name> verification code is: 123456

You can override the language by sending in a locale parameter for any of our dozens of supported languages. You can also provide a template to support use cases like do not share warnings, origin bound SMS codes, and your own verbiage.

Bring your own one-time passcode

If you already have token validation and generation logic and would like to keep those systems in place, you can do so. We have a feature where you can use your own OTP and still use our pre-screened message templates and localizations for both text and voice. Contact Twilio Sales and we'll help you enable this option.

Know the limits and timeouts

Token Validity Period

Once generated, tokens are valid for 10 minutes. We are unable to change the timeout for token validity for your application. If your users make another request within the 10 minutes, they will receive the same token.

Rate limits

Rate limits are in place to help prevent fraud and protect your application and Twilio's servers. For example, we limit send attempts to the same entity (phone number or email). Our built in rate limits are sufficient for most customers, but you can also define your own rate limits. In addition, this blog post covers how to test and develop with the Verify API without getting rate limited.

With the 10 minute timeout, the majority of the delay you'll see during verification will be user input and not API requests.

Check out this document for more details about Twilio's REST API best practices and rate limits.

Limit SMS messages to one message segment to avoid extra cost

SMS messages sent with Programmable Messaging, Verify, and Authy are priced per message segment.

Character limits for message segments depend on the types of characters used:

Character set Character limit
Contains only GSM characters 160 characters
Contains Non-GSM characters (e.g. ó and ¡) 70 characters

When a message doesn’t fit into one segment, it’s automatically broken into two or more segments and you'll be billed for all of those segments. Therefore we recommend constructing your OTP messages to fit into one segment or be aware when it's going to take more than one. Use the segment calculator to confirm how many segments a message will result in.

Twilio Verify/Authy and message segments

The default, standard messages that Verify and Authy provide currently all fit within one message segment, except in the following circumstances:

  • Messages are sent in these language locales: pt, pt_BR, cs, el
  • do_not_share_warning_enabled is set to true. When true, if appending the privacy warning results in a message that takes more than one segment, then the privacy warning won't be appended.
  • psd2_enabled is set to true
  • Template feature is used
  • Custom message feature is used

In the case of these exceptions, your specific message may still fit within one message segment, depending on parameters that affect character length like friendly_name, code_length, locale, and other customization options that you select.

Prepare for the unexpected

Monitor verification conversion rates

Monitor based on geography to detect spikes in unchecked verifications that could indicate abuse or delivery issues.

​​Create Twilio account usage triggers

Get notified if something goes wrong or if abuse happens on your account with Twilio's usage triggers, available via the API, CLI, or Twilio Console.

Add error handling

Finally, leverage the Verify and Lookup error dictionary to handle errors appropriately in the customer application.

Still wondering about verification? We're happy to help.

Now that you have all of the best practices, you can send an SMS OTP in less than 5 minutes with the Verify API with Twilio's Code Exchange. Learn more about the parameters supported in the API documentation or check out one of our quickstarts in the language of your choice.If you have questions about your implementation, please reach out. We can't wait to see what you build and secure!

Rate this page:

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd by visiting Twilio's Stack Overflow Collective or browsing the Twilio tag on Stack Overflow.

        
        
        

        Thank you for your feedback!

        Please select the reason(s) for your feedback. The additional information you provide helps us improve our documentation:

        Sending your feedback...
        🎉 Thank you for your feedback!
        Something went wrong. Please try again.

        Thanks for your feedback!

        Refer us and get $10 in 3 simple steps!

        Step 1

        Get link

        Get a free personal referral link here

        Step 2

        Give $10

        Your user signs up and upgrade using link

        Step 3

        Get $10

        1,250 free SMSes
        OR 1,000 free voice mins
        OR 12,000 chats
        OR more