Authy is a simple REST API that does all the heavy lifting, so you can add two-factor authentication to your website or app
in just a few hours.
This guide will make use of this resources as we build a simple web app using the Authy API.
Full source code for this app can be found
You will find everything you need in
There are 2 main parts to implement the Authy API
- Adding new users: involves creating a html form that takes the user's phone number and submits it to the Authy API.
- Verifying users: involves adding a field to the login form were the user enters the token and then submitting it to Authy.
Part 1: Adding new user
First we are going to create a page in our users control panel (well call it /enableauthy). In this page we'll create a simple form that takes the persons phone number
and area code.
). The html id's
=text_field "cellphone", :placeholder => "Enter your cellphone", :id => "authy-cellphone"
=text_field "country_code", :id => "authy-countries", :placeholder => "Enter your country"
- If set on the text-field were the user inputs his cellphone it will automatically run phone validations on the client-side.
- If set on the text-field were the user inputs his area code will produce an auto-complete drop down with a list of countries with area-codes. This makes
it really easy for the user to enter his area-code.
At this point you can send the users email, phone number and country code to Authy.
@authy_user = Authy::API.register_user(:email => current_user.email,
:cellphone => params[:user][:cellphone],
:country_code => params[:user][:country_code])
current_user.authy_id = @authy_user.id
@errors = @authy_user.errors
If everything goes well:
Authy will return you the Authy ID of the users. This is an integer > 0. You need to store this id your users database.
If not a hash with errors in plain English is sent back. You should display this errors in the form so that the user can correct the inputs.
Part 2: Verifying users
After the user has register to Authy in your website you get back an Authy ID. Next time user wants to log-in
you can use the Authy ID to verify the two-factor token.
There are many ways of doing this which depends on your application and the user experience you wish to create.
In this example we plan to support users that have two-factor authentication on, and some which don't.
The easiest way is to do this is separating the authentication in 2 screens.
- The first screen is your usual login form were the user inputs his username and password.
- The second screen is were the user inputs his Authy Token if Authy is enabled in his account.
You can quickly check if a user has Authy enabled by checking your database. Assuming you called the Authy ID record in your database authy_id, you can check if authy_id field
for the user is > 0. If so you can assume Authy is enabled.
Here's the function that validates username and password and redirects to the two-factor auth if authy is enabled:
@user = User.find_by_email(params[:user][:email])
if @user && @user.authenticate(params[:user][:password])
#username and password is correct
if(@user.authy_id != 0) #user is using two-factor
Authy::API.request_sms(:id => @user.authy_id) #request the API to send and sms.
#Rails sessions are tamper proof. We can store the ID and that the password was already validated
session[:password_validated] = true
session[:id] = @user.id
redirect_to url_for(:controller => "sessions", :action => "two_factor_auth")
flash[:notice] = "Successfully authenticated without two-factor"
flash[:error] = "Wrong username, password."
@user = User.new
Basically, when the user wants to log-in, you use his e-mail to locate the record in the database. Then you try to authenticate him.
The authenticate function will check his username and password and also if the user has Authy enabled.
If so you will redirect the user to the second page were he can enter his Token and complete his authentication.
Here's the function that does the second factor authentication:
@user = User.find(session[:id])
token = params[:token]
if @user && session[:password_validated] && @user.verify_token(token)
@user.authy_used = true
@user.save(:validate => false)
session[:password_validated] = nil
session[:id] = nil
flash[:success] = "Securely signed in using Authy"
flash[:error] = "Wrong token"
Token verification involves sending the token and the id. Authy will respond HTTP status 200 if the token is correct.
token = Authy::API.verify(:id => self.id, :token => token)
The function simply passes the authy_id and the token the user entered. Then it check if the response is HTTP status 200, if so it returns true.
To prevent users account getting locked down, Authy won't check the tokens until we are certain the user has completed the registration process.
If you want to verify token's anyway, you can pass ?force=true to verify.