Authentication on Rails
Authentication can definitely get tricky and if you haven't done it or don't have much experience you may take longer than needed, luckily you came across this blog and you will get through it quickly.
The first step will be within the User table. when creating this table you will need to create a column with a "password_digest" column.
class CreateUsers < ActiveRecord::Migration[7.0]
def change
create_table :users do |t|
t.string :username
t.string :email
t.string :password_digest
# t.references :rating, foreign_key: { to_table: 'users' }
t.timestamps
end
end
end
After that you finished creating the column you will need to head over to the User's controller. Here you will make a def create
method. This method will look like this:
class UsersController < ApplicationController
skip_before_action :authenticate_user, only: [:create,:index]
def create
user = User.create(
username: params[:username],
email: params[:email],
password: params[:password],
password_confirmation: params[:password_confirmation])
render json: user, status: :created
end
def index
render json: User.all, status: :ok
end
end
You now have the column for the password and the create method for user. Now we need to make a controller for the session. In the terminal lets put this code: rails g controller sessions_controller
. This will be the what will generate our cookie in our browser so the user does not have to keep signing in. In this controller lets make a create and destroy method.
class SessionsController < ApplicationController
skip_before_action :authenticate_user, only: :create
def create
user = User.find_by(username: params[:username])
if user&.authenticate(params[:password])
session[:user_id] = user.id
render json: user, status: :created
else
render json: { error: "Invalid username or password" }, status: :unauthorized
end
end
def destroy
session.delete :user_id
head :no_content
end
end
Let's recap before we go onto our last step. We created a column in the user's table, this column had a key of password_digest
with a value of string
. We then headed over to the user User's controller and inserted some code so we can create new users. After that we created a controller named sessions_controller, this will give the cookie to the browser so the user does not need to sign in everytime. Once we have these 3 steps we will go into the application controller and create an authenticate user method
class ApplicationController < ActionController::API
def authenticate_user
@current_user = User.find_by(id: session[:user_id])
render json: { error: "Not authorized" }, status: :unauthorized unless
@current_user
end
end
If you are wondering why make this method and why here, here's why. The application controller is the highest level of our application so whatever we create here, every controller will inherit it so we can utilize it, another good example would be the rescue methods and responses we give to the errors(I will not be explaining that here). With this reason, I made this method because we need to make sure that the user is signed in before all of the options are made available.
I know that I said this would be the end of the steps by I was just joking(I also forgot to include them earlier), there are 2 more steps. The first one is going into the User Model. Here you need to insert has_secure_password
.
class User < ApplicationRecord
has_secure_password
end
The second step would be inserting a param: :password_confirmation
in the private section.
class UsersController < ApplicationController
private
def user_params
params.permit(:username,:email, :password, :password_confirmation)
end
end
We are now at the end of this blog and I'd like to congratulate you because you now know how to work with authentication.