Send/Verify OTP from Rails application with 2FACTOR

Kavita Jadhav
3 min readNov 20, 2020

--

https://media.licdn.com/dms/image/C4E12AQGMEnJSlG2xWw/article-cover_image-shrink_600_2000/0/1520220232172?e=2147483647&v=beta&t=0_dO83yLFnCN2dOq2E_6VC52Y3YBd8m3LMImK9S7qLE

Here we will be using 2FACTOR authentication API to send OTP from the Rails application in India. With a free trial account, you will get 100 OTP SMS, 100 Transactional SMS and 50 voice SMS. Follow the below steps to get started!

Create a new 2FACTOR account

Visit the 2FACTOR portal and create your free trial account using your email address and phone number. A unique API key will be generated for your account. You will receive this API key in your email inbox. You can also find the same on the 2factor portal in your account summary. Check the available SMS balance there.

Install HTTP party gem

Add the httparty gem in your Gemfile. Run the bundle install command to install the newly added gem. This will help in making an HTTP request to the 2FACTOR portal.

Add column session_key in the users table.

Every time when OTP is sent to a mobile number from 2FACTOR, it generates a new session_key. You will need this session_key to verify OTP. Hence it needs to be stored. I am adding the session_key column in the users table. You can choose to store it in some other place as well.

Create a new migration and run it with the command rails db:migrate

class AddSessionKeyInUsers < ActiveRecord::Migration[6.0]
def change
add_column
:users, :session_key, :string
end
end

Add routes to send/verify OTP

Now it's time to make an API request to the 2FACTOR portal from your application. create a new file two_factor.rb in the app/lib directory and add the below code in the two_factor.rb file. Don't forget to replace your TWO_FACTOR_API_KEY.

require 'httparty'

class TwoFactor
include HTTParty

TWO_FACTOR_API_KEY
= '253f2a8t4-190a-fkl3-1da5-09jd45bh82ehds20'

def self
.send_passcode(phone)
response = get("https://2factor.in/API/V1/#{TWO_FACTOR_API_KEY}/SMS/#{phone}")
response.parsed_response
end

def self
.verify_passcode(session_key, code)
response = post("https://2factor.in/API/V1/#{TWO_FACTOR_API_KEY}/SMS/VERIFY/#{session_key}/#{code}")
response.parsed_response
end
end

Now call this method from your controller/model. Here I have added a new method in the user's class to send passcodes as well as to store the session key mentioned earlier. Call the method from the controller as below:

class User < ApplicationRecord
def
send_passcode
response
= TwoFactor.send_passcode(mobile)
if response['Status'].downcase == 'success'
update_column(:session_key, response['Details'])
true
end
end
end
class AuthenticationController < ApplicationController
def
sign_in
login_params
= params.permit(:mobile, :username)

@user = User.find_by_mobile(login_params[:mobile])
if @user && @user.send_passcode
render(json: {message: 'Sent passccode'}, status: :ok)
else
render(json: {error: 'failed to send passcode'}, status: :unauthorized)
end
end
end

By default, 2FACTOR will generate 6-digit OTP. To send 4 digit OTP you can make the below changes in two_factor.rb file.

def self.send_passcode(phone)
response = get("https://2factor.in/API/V1/#{TWO_FACTOR_API_KEY}/SMS/#{phone}/AUTOGEN3")
response.parsed_response
end

You can also generate a passcode within your application itself. To explore more such options please go through 2factor API documentation.

Now it's time to verify your passcode. Add a new controller method to accept and verify passcode in AuthenticationController as below:

def verify
verification_params
= params.permit(:mobile, :passcode)
@user = User.find_by_mobile(verification_params[:mobile])
if @user && @user.verify_passcode(verification_params[:passcode])
render(json: {user: @user}, status: :ok)
else
render(json: {error: 'Failed to verify passcode'}, status: :unauthorized)
end
end

In the verify method you can also perform your custom actions like setting the current user and creating JWT after verifying the passcode.

We also need to add the verify_passcode method in the user model. Here we will use the session_key generated while sending the passcode to verify the mobile number and passcode in 2 factors.

def verify_passcode(passcode)
TwoFactor.verify_passcode(session_key, passcode)['Status'].downcase == 'success'
end

This method will return the true value to the controller if a valid passcode is given.

Thats it! Now you can start sending SMS OTPs from your application.

--

--

Kavita Jadhav
Kavita Jadhav

Written by Kavita Jadhav

Application Developer @ Teladoc Health

No responses yet