Simple OTP Authentication with Rails API and Twilio - PART I
I am super excited to be sharing with you a simple authentication flow using Rails API and Twilio. The Twilio service allows us send messages from our application to our mobile device as SMS. We can leverage this flow to build a simple authentication system. To get started, we would be creating a new Rails application. For the purpose of this article, we would be using Rails API because at the end of this article, we would be integrating the Rails API with React Native to create an OTP authentication screen. Amazing right? Let's get into it.
First, we would create a new Rails API application, we would be striping out minitest and we would be using PostgreSQL as our database layer. To learn how to setup PostgreSQL on your machine for Mac OS and Windows, Check out this link below.
Setting up PostgreSQL in Mac, Windows and Linux
Back to our steps, run the command below to create a new Rails API application with Postgres.
rails new twilio_otp_authentication --api -T -d=postgresql
Next, change directory to the Rails app, using this command
cd twilio_otp_authentication
Next, let's create the database in postgresql. To do that, we simple need to run
rails db:create
On our terminal we should see this
Created database 'twilio_otp_authentication_development'
Created database 'twilio_otp_authentication_test'
Next, let's create our User model with the following attributes: country_code, phone_number, name. (Note this is a very basic model, we might decide to add more attributes later). Run the command below to create our User model
rails g model User country_code phone_number name
We should see something like this on our terminal to indicate that the model have been created.
Running via Spring preloader in process 61795
invoke active_record
create db/migrate/20200907132410_create_users.rb
create app/models/user.rb
Next, let's check the db folder
and inside it, migrate folder
, we should see our new migrate file. Open it. We need to verify that the file was properly created. We should have something like this
class CreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
t.string :country_code
t.string :phone_number
t.string :name
t.timestamps
end
end
end
Next we are going to change the datatype for phone_number from string to integer so our file should look like this
class CreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
t.string :country_code
t.integer :phone_number
t.string :name
t.timestamps
end
end
end
Next, run rails db:migrate on your terminal to create the User schema and table on the Postgres database.
rails db:migrate
On your terminal you should see something like this to indicate a successful migration.
== 20200907132410 CreateUsers: migrating ======================================
-- create_table(:users)
-> 0.0080s
== 20200907132410 CreateUsers: migrated (0.0080s) =============================
Next, We need to create a twilio account.(If you don't already have one). To do that, visit Twilio Website.
Next, create an account by clicking on the signup button
If you already have an account login with your email and password details
Twilio might prompt you to secure your account with a two-factor authentication, you can setup later for the purpose of this exercise. But if you are using this for a production codebase, I would advise you do it to get an extra level of protection and security. For this article, I would click setup later.
You should see your twilio dashboard like this
Next, click on the link above the dashboard icon to reveal a dropdown,
Next, click on Create New Project
Next, You may be asked to verify your email, The image should look like this
Go to your email and verify, you should see a screen like this to verify phone number
Next, Fill the survey or skip to go to dashboard, your dashboard should look like this
Next, click on the three-dot menu icon on the sidebar to reveal all services.
Next, click on the Verify service, as shown in the image below
.
Next, create a Verify service by entering a friendly name, you can use the name of the app as TwilioOTPAuthentication
Next, click on settings on the Verify service to see the Service ID(SID). (take note of this ID, it would be used in our Rails API) You can decide to change the OTP Code length from 6 to 4 if you prefer a 4 digit code sent during the verification process as shown in the image below
Next, go to the project console(Click on the dropdown at the top of the dashboard icon and select the project TwilioOTPAuthentication
) to see the Auth Token and Account ID, this would also be used in our Rails API as shown below
Next, on your rails API project, go the gemfile at the root directory and add the twilio-ruby sdk. Add this to your gemfile
gem 'twilio-ruby'
Run bundle install
bundle install
Next, for performance we would need to setup Redis and Sidekiq for queuing the auth code message that would be sent from twilio 3rd party integration to our mobile device. To do that we need to ensure that redis is installed on our machine. For steps on how to setup Redis, check out this article Install Redis on Windows and Mac.
Next, add the following gems to your gemfile
gem 'redis'
gem 'redis-rails'
Run bundle install
on your terminal
Next, let's install sidekiq. To do that, add the following gem to your gemfile
gem 'sidekiq'
Run bundle install
on your terminal
Next, we need to add two files to setup sidekiq on your rails application
- sidekiq.rb
- sidekiq.yml
Create the file sidekiq.yml
inside the config folder in your rails app with the following content
development:
:concurrency: 5
production:
:concurrency: 5
:queues:
- high
- default
- mailers
From the code above we are specifying the concurrency on both development and production environment and the types of queue priority.
Create the file sidekiq.rb
inside the initializers folder in the config folder with the following content
Sidekiq.configure_client do |config|
config.redis = { url: 'redis://127.0.0.1:6379/0', size: 1, network_timeout: 5 }
end
Sidekiq.configure_server do |config|
config.redis = { url: 'redis://127.0.0.1:6379/0', size: 7, network_timeout: 5 }
end
Sidekiq::Extensions.enable_delay!
From the code above we are configuring both sidekiq client and server to talk to each other. We have the default Redis url which is the url hook that receives and sends information between client and server. We are also specifying the size of the threads and the time before network timeout. We also decided to enable delay.
To make this more production friendly, we would move the url to an environment variable file. To get started, we would need to add the dotenv-rails gem to our Gemfile and run bundle install to install it.
gem 'dotenv-rails', require: 'dotenv/rails-now'
bundle install
Next, we would create a .env
file at the root directory of our project and gitignore it. Our .env file would contain the following
REDIS_URL=redis://127.0.0.1:6379/0
and then our sidekiq.rb would look like this
Sidekiq.configure_client do |config|
config.redis = { url: ENV.fetch('REDIS_URL'), size: 1, network_timeout: 5 }
end
Sidekiq.configure_server do |config|
config.redis = { url: ENV.fetch('REDIS_URL'), size: 7, network_timeout: 5 }
end
Sidekiq::Extensions.enable_delay!
Next, we need to a configuration to use sidekiq in our development environment. Open development.rb under the environments folder in the config folder and add these lines under the config.active_storage.service = :local
config.active_job.queue_adapter = :sidekiq
config.active_job.queue_name_prefix = "twilio_otp_authentication_#{Rails.env}"
And that is it!!!. š š š š š š. In the second part of this article, I would be showing you how to add the authentication service, create a send_pin_code worker file to handle our background process, create a route to test things out on Postman and not forgetting testing for our authentication service. See you in the next one!