In this tutorial, we are going to build an authentication system (like login/sign-up) from scratch using the bcrypt gem.
First, we need to generate a new project, to get to know how to do that please refer my previous tutorials. Links are added to the curriculum.
After setting up the project, next, we need to install the library called Bcrypt to our Gemfile. The bcrypt library is used to hash and salt passwords in a secure way.
gem 'bcrypt`
Now run bundle command to install the gem in the terminal.
bundle
First, you will need to create a model to store user information.
rails g model User
Now go to the app > db > migrations > timestamp_create_users.rb file in the text editor like sublime and add the following code into that file.
create_table :users do |t|
t.string :email
t.string :password_digest
t.timestamps
end
Now run the migration command to migrate the database but first of all, we need to create the database then need to migrate.
rake db:create
rake db:migrate
It's time to add code to our user model so that the model will support the authentication. Go to app > model > user.rb. Please always use the text editor to open the files. Now add the following code into that file.
has_secure_password
validates :email, uniqueness: true, presence: true
has a secure password: It adds two additional properties to your user:
a) password
b) password confirmation
In addition, it adds a number of different validations (presence, length with a maximum of 72, and confirmation). And also, it adds a method called authenticate which allows you to authenticate the user against the database.
Validates: It will validate the presence, uniqueness and presence of email while saving the user.
First of all, you will generate a dashboard controller, for that run the following command.
rails g controller dashboard
Now go to the app > controllers > dashboard_controller.rb and a show method there.
def show
end
And then root the rails app to dashboard show page.
root 'dashboard#show'
Now when you hit the localhost:3000, it will redirect to dashboard show page.Next, you will need to generate the sessions controller where login/logout are handle.
rails g controller sessions
Now go to the app > controllers > sessions_controller.rb and the following methods.
def new
end
def create
end
def destroy
end
And Finally, generate our users' controllers.
rails g controller users
Now go to the app > controllers > users_controller.rb and a the following methods.
def new
end
def create
end
Now update our routes for the users and sessions
get 'login', to: 'sessions#new'
get 'logout', to: 'sessions#destroy'
resources :sessions, only: [:create]
resources :users, only: [:new, :create]
You can also check the routes by running the following command under the project path in the terminal & also see the reference image below:
rake routes
Now you will add tell the application to check the user logged in or not every time when the user accesses the application. Go to app > controllers > application_controller.rb. Application controller is the root controller and calls every time before the called controller. let's say there is a request coming to open the sign-up page then the app will first go the application controller and then go to the users controller.
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :require_valid_user!
def current_user
if !session[:user_id].blank?
@user ||= User.find(session[:user_id])
end
end
def require_valid_user!
if current_user.nil?
flash[:error] = 'You must be logged in to access that page!'
redirect_to login_path
end
end
end
Now it's time to work on the session controller. This controller contains methods that are used to log in/out of the app. Open the app > controllers > sessions_controller.rb in the text editor. You will have to work on the create and destroy methods.
def create
reset_session
@user = User.find_by(email: session_params[:email])
if @user && @user.authenticate(session_params[:password])
session[:user_id] = @user.id
flash[:success] = 'Welcome back!'
redirect_to root_path
else
flash[:error] = 'Invalid email/password combination'
redirect_to login_path
end
end
def session_params
params.require(:session).permit(:email, :password)
end
The create method handle the process of logging in:
2 . Destroy Method
skip_before_action :require_valid_user!, except: [:destroy]
def destroy
reset_session
end
Everything were setup, now you will have to create a user, to handle that open up app > controllers > users_controller.rb and modify some code.
class UsersController < ApplicationController
skip_before_action :require_valid_user!
before_action :reset_session
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
session[:user_id] = @user.id
flash[:success] = 'You have successfully created an account!'
redirect_to root_path
else
render :new
end
end
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end
end
Now, backend functionality is complete. it's time to work on the frontend. First of all, we need to add the bootstrap library and wrap the rendering of our views in a div with a class of container.
<head>
<%= stylesheet_link_tag 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css' %>
</head>
<body>
<div class='container'>
<%= yield %>
</div>
</body>
Now you will modify the landing page i.e dashboard show page. There will be a link to sign in and sign up for the user. Open up the file app > views > dashboard > show.html.erb
<h1>Dashboard</h1>
<p>Welcome to your dashboard.</p>
<% if flash[:success] %>
<div class='alert alert-success'><%= flash[:success] %></div>
<% end %>
<%= link_to 'Click here to log out.', logout_path %>
Now you will have to create a new user and create a form for that, open up the app >views > users > new.html.erb and add the following code.
<h1>Sign Up</h1>
<p>Create a new account using the form below. All fields are required.</p>
<% if @user.errors.any? %>
<div class='alert alert-danger'>
<p>Please correct the following errors:</p>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= form_for @user do |f| %>
<div class='form-group'>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
</div>
<div class='form-group'>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
</div>
<div class='form-group'>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
</div>
<%= f.submit 'Register', class: 'btn btn-primary' %>
<% end %>
<p >
Already have an account? <%= link_to 'Click here to sign in.', login_path %>
</p>
We have signed up and a dashboard page but we don't have a login page for now. let's create this page.Open up the app > views > sessions > new.html.erb and the following code.
<p>Please log in to continue.</p>
<%- if flash[:error] %>
<div class='alert alert-danger'><%= flash[:error] %></div>
<% end %>
<%= form_for :session, url: sessions_path do |f| %>
<div class='form-group'>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control', placeholder: 'Email' %>
</div>
<div class='form-group'>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control', placeholder: 'Password' %>
</div>
<div class='form-group'>
<%= f.submit 'Log In', class: 'btn btn-primary' %>
</div>
<% end %>
<p >
New User? <%= link_to 'Click here to create an account.', new_user_path %>
</p>
So this is the tutorial about to add basic authentication in ruby in rails application
.
https://steemit.com/utopian-io/@amn/how-to-add-exception-notification-in-ruby-on-rails-using-the-exception-notifies-gem
https://steemit.com/utopian-io/@amn/how-to-add-email-confirmation-while-sign-up-using-devise-in-ruby-on-rails
https://steemit.com/utopian-io/@amn/how-to-upload-images-in-ruby-on-rails-using-paperclip