In this blog we will create sign-up and login Api with
devise. For this we will override registration controller and session controller of devise. For this you can follow
devise documentation.
So, in Gemfile -
gem 'devise'
Then run bundle install
As we know that we need to run the devise generator
$ rails generate devise:install
Now, configure the default Devise modules with User model
$ rails generate devise User
For overriding devise's controller, create your custom controllers using the generator
$ rails generate devise:controllers User
We have to generate auth_token for every user for authentication
So, in User.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
#==== Callbacks =======================================================
before_create :generate_auth_token
def generate_token
SecureRandom.urlsafe_base64
end
private
def generate_auth_token
if self.auth_token.blank?
begin
self.auth_token = generate_token
end while User.exists?(auth_token: self.auth_token)
end
end
end
We have to override routes also.
In roures.rb
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
devise_for :users, controllers: {
registrations: 'users/registrations',
sessions: 'users/sessions'
}
devise_scope :user do
root to: "users/sessions#new"
post '/sign-up' => 'users/registrations#create'
post '/sign-in' => 'users/sessions#create'
end
end
Now, we will override registration controller -
So, in users/registrations_controller.rb-
class Users::RegistrationsController < Devise::RegistrationsController
=begin
********************************************************************
POST /resource.json
params -
{
"user":{
"first_name":"xyz",
"last_name":"abc",
"phone_number":"0987654321",
"email":"xyz@xyz.com",
"password":"12345678",
"password_confirmation":"12345678"
}
}
********************************************************************
=end
def create
resource = User.new(configure_sign_up_params)
respond_to do |format|
if resource.save
format.json { render json: {resource: resource}, status: :created }
else
format.json { render json: {error: resource.errors.full_messages}, status: :unprocessable_entity }
end
end
end
protected
# If you have extra params to permit, append them to the sanitizer.
def configure_sign_up_params
params.require(:user).permit(:email, :first_name, :last_name, :phone_number, :password, :password_confirmation)
end
end
Above code will return user obejct as json -
{
"resource": {
"auth_token": "NywmeVFFU1eyZE_BGBA4og",
"id": 1,
"first_name": "xyz",
"last_name": "abc",
"phone_number": "0987654321",
"created_at": "2017-01-12T09:57:18.000Z",
"updated_at": "2017-01-12T10:03:00.000Z",
"email": "xyz@xyz.com"
}
}
For login we have to override sessions_controller.rb
class Users::SessionsController < Devise::SessionsController
#====== Filters ===============================================
prepend_before_action :require_no_authentication, :only => [:create]
skip_before_action :verify_signed_out_user, if: -> { request.format.json? }
=begin
*********************************************************
POST /sign-in.json
params - {"user":{"email": "xyz132@xyz.com", "password": "12345678"}}
*********************************************************
=end
def create
respond_to do |format|
resource = User.find_for_database_authentication(email: params[:user][:email])
if resource and resource.valid_password?(params[:user][:password])
resource.auth_token = resource.generate_token
format.json { render json: {resource: resource}, status: :ok }
else
format.json { render json: {error: 'Sign in not successful'}, status: :unprocessable_entity }
end
end
end
end
On successful it will also return user object as josn -
{
"resource": {
"auth_token": "NywmeVFFU1eyZE_BGBA4og",
"id": 1,
"first_name": "xyz",
"last_name": "abc",
"phone_number": "0987654321",
"created_at": "2017-01-12T09:57:18.000Z",
"updated_at": "2017-01-12T10:03:00.000Z",
"email": "xyz@xyz.com"
}
}
Note that In api authentication we should not generate session for user because it should handle at front-end.
If you have web app also than you have to create session for user and use respond with html too.