As of November 2022, Twilio no longer provides support for Authy SMS/Voice-only customers. Customers who were also using Authy TOTP or Push prior to March 1, 2023 are still supported. The Authy API is now closed to new customers and will be fully deprecated in the future.
For new development, we encourage you to use the Verify v2 API.
Existing customers will not be impacted at this time until Authy API has reached End of Life. For more information about migration, see Migrating from Authy to Verify for SMS.
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. We have a number of resources, such as JavaScript helpers and API libraries for most languages. This guide will make use of these resources as we build a simple web app using the Authy API.
Full source code for this app can be found here
You will find everything you need in on github
There are two main parts to implement an Authy API integration:
First we are going to create a page in the users control panel (we will call it /enableauthy). In this page we'll create a simple form that collects the phone number and area code.
This form uses the Authy JavaScript samples found here. The html IDs authy-cellphone
and authy-countries
are special IDs recognized by this JavaScript.
_10%label_10 Cellphone_10= text_field "cellphone", :placeholder => "Enter your cellphone", :id => "authy-cellphone"_10_10%label_10 Country_10= text_field "country_code", :id => "authy-countries", :placeholder => "Enter your country"_10_10= submit "Submit", :class => "btn"
The scripts use ID s to help you easily build this form. These are the id's used
At this point you can send the users email, phone number and country code to Authy.
_15def register_authy_15 @authy_user = Authy::API.register_user(_15 :email => current_user.email,_15 :cellphone => params[:user][:cellphone],_15 :country_code => params[:user][:country_code]_15 )_15_15 if @authy_user.ok?_15 current_user.authy_id = @authy_user.id_15 current_user.save_15 else_15 @errors = @authy_user.errors_15 render 'enable_authy'_15 end_15end
If everything goes well, the API will return the user's Authy ID. This is represented as an integer which you need to store in your users database or directory. In the case of an error, a hash in plain English is returned. The language used is designed for you to display to the user to help them resolve the situation.
After you have registered the user in the Authy service and stored the resulting Authy ID against the user's profile in your application, the next time you process the user login, you use the Authy ID to verify the two-factor token they should provide.
Implementing the request for a second factor during the login can vary depending on the design of your application and the end user experience you wish to create. In this example we plan to support users who opt-in for two-factor authentication. Therefore there will be a mix of user accounts that are enabled and some that are not. The easiest way to implement this is to separate the authentication process across two screens.
Remember you need to manage the link between your user identities and the Authy user. Your database or user directory should ensure the AuthyID is stored with each user profile that has been registered.
Here's the function from our sample application that validates username and password and redirects to the two-factor authentication page if authy is enabled:
_23def create_23 @user = User.find_by_email(params[:user][:email])_23_23 if @user && @user.authenticate(params[:user][:password])_23 # username and password is correct_23 if(@user.authy_id != 0) #user is using two-factor_23 Authy::API.request_sms(:id => @user.authy_id) # request the API to send and sms._23_23 # Rails sessions are tamper proof. We can store the ID and that the password was already validated_23 session[:password_validated] = true_23 session[:id] = @user.id_23 redirect_to url_for(:controller => "sessions", :action => "two_factor_auth")_23 else_23 sign_in(@user)_23 flash[:notice] = "Successfully authenticated without two-factor"_23 redirect_to @user_23 end_23 else_23 flash[:error] = "Wrong username, password."_23 @user = User.new_23 render 'new'_23 end_23end
When the user wants to login, you use their email (or whatever user identifier you are using) to locate their user profile in the database or directory. The authenticate function will check username and password and if the user has been Authy enabled. If so, redirect the user to the second page were they enter the token and complete the authentication. Here's the function for the second factor authentication:
_16def create_two_factor_auth_16 @user = User.find(session[:id])_16 token = params[:token]_16 if @user && session[:password_validated] && @user.verify_token(token)_16 sign_in(@user)_16 @user.authy_used = true_16 @user.save(:validate => false)_16 session[:password_validated] = nil_16 session[:id] = nil_16 flash[:success] = "Securely signed in using Authy"_16 redirect_to @user_16 else_16 flash[:error] = "Wrong token"_16 redirect_to new_session_path_16 end_16end
Token verification involves sending the token and the id. Authy will respond HTTP status 200 if the token is correct.
_10def verify_token(token)_10 token = Authy::API.verify(:id => self.id, :token => token)_10_10 token.ok?_10end
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.