You’ve undoubtedly done something like this before:
That’s the SMS phone verification for AirBnB, which uses Twilio to allow hosts and guests to chat without sharing their actual phone numbers. In this tutorial, we’ll integrate SMS phone verification into a Rails 4 app using AJAX and Twilio.
Warning: There are a bunch of great reasons to grab a user’s phone number, but if your end goal is two-factor authentication, you should close this tutorial right now and use Authy instead. 2FA is a tricky beast, wrought with edge cases and security concerns — it’s typically a bad idea to roll your own.
However, if you’re looking to verify phone numbers in your Rails app for some other reason, by all means press on.
Create the Model
First we need a Rails project (we’ll use a fresh one for the purposes of this tutorial, but it shouldn’t be too hard to replicate these steps to integrate SMS verification into your preexisting Rails 4 app):
Add the Twilio gem to your
:
Install your gems:
Create a
model to store:
the phone number itself
a randomly generated PIN
A flag indicating if the number has been verified
Create the database and run the migration:
Now we have the M in MVC. Let’s do the C.
Create the Controller
As mentioned before, our verification process has three steps:
The user enters a new phone number
Our app creates the phone number row and sends the user a PIN to enter back into the form
Our app verifies that the PINs match for the given phone number.
Add this code to
to create a route for each step:
Create the
controller we just referenced in those routes:
Inside the controller (found at
), add a straightforward
action that creates a
that we’ll use in a
block in the view:
The beginnings of our C are in place. On to the V.
Create the View
From the user’s perspective, SMS verification involves three steps:
Enter a New Phone Number
Verify the PIN
Receive a success or failure message
To avoid jarring page loads, we’ll use AJAX to complete the process on a single page like we saw in AirBnB’s example.
But before we create the phone verification form, let’s address a slight problem: default Rails views are hideous. We can remedy that by simply including an externally hosted Bootstrap stylesheet.
In
, add this line above where the application stylesheet is included:
Then replace that files current
with this:
Now that our page won’t make our eyes bleed, we can create a new phone number view:
Add this code to that file to create a form for Step 1:
Make sure everything looks okay. Start your Rails server:
Visit
in a browser and check out your form. Should look something like this:
Before we wire up that “Send PIN” button, add this to the same file to compete the view:
This code creates a from with:
A hidden field to store the phone number (we will update this field using AJAX after the user completes Step 1).
A text field for entering the PIN
A submit button
It also adds a
where we’ll display a message after we attempt to verify the PIN. Refresh your page and make sure you can see the elements.
But wait! We don’t need to see Steps 2 and 3 yet!
Add this CSS to
(Rails auto-created that file for you) to make them disappear when the page loads. We’ll reveal them at the appropriate time with AJAX:
Refresh the page and ensure that you’re back to only seeing Step 1. With our finished view, we’ll head back to the controller and model to make it work.
Generate a PIN and send it via SMS
For Step 2, we need a
action in our controller that will do four things:
Create the phone number entered into the form (or find it if it already exists)
Generate a PIN
Send the PIN via SMS
Return JavaScript to reveal and prepare Step 2 of the view
Add this action to
inside
:
The astute reader will notice that we used two methods on
that don’t exist yet exist.
Add this method inside your
class in
to generate a four digit PIN:
This method, called by the controller when a phone number is created, generates a PIN and saves the record.
Before we can send this PIN via SMS, we need three things from Twilio:
Your account SID
Your auth Token
An SMS enabled phone number
Go to your Twilio account dashboard and find your account SID and auth token:
Also head over to your phone numbers list and find one you want to use for this app.
We’ll set these values as environment variables along with your Twilio phone number. Phil Nash wrote a great post on the multitude of ways to set environment variables in Ruby, but for the sake of this tutorial, we’ll do it in the simplest way possible. Kill your server, then punch this into the same terminal window:
Add two methods to our
class to send an SMS.
This method creates a Twilio REST client:
This method sends the PIN via SMS:
Last thing our
action does is to return JavaScript that will:
Add the phone number to our hidden field
Reveal Step 1 and hide Step 2
Move the focus onto the PIN input
Create a new file:
Add this to that file:
And that’s it for
! Restart your server, reload your page and give it a try!
Verify the PIN
The third and final step in our phone verification is the easiest: we check to see if the entered PIN matches the generated PIN. If so, we update the verified flag on the phone number record and update the page with a happy message. Otherwise, sad message.
Add this
action to the
:
You’ll again notice that
isn’t a thing yet. Add this to your
model:
Finally, let’s write our JavaScript to update the status message in the view. Create a new file:
In that file, paste in this code that will display the appropriate status message depending on if the phone number is successfully verified, then reveal the
.
That’s it!
Next Steps
This should get the ball rolling on verifying phone numbers in your Rails app, but it’s not a complete yet. You’ll want to code up some answers to a few questions:
What if the entered phone number is already verified?
What’s the UX if they get the PIN wrong? Should there be a resend PIN button?
What keeps someone from bruteforcing the PIN? Should the PIN expire after X tries or Y minutes?
If you have any questions or suggestions on this tutorial, or would like to show off what you’ve used phone verification for, hit me up at gb@twilio.com or @greggyb.
Happy Hacking!
SMS Phone Verification in Rails 4 using AJAX and Twilio