Back

Simple User Authentication

Many rails applications use gems such as Devise to add user functionality to the application. This may be feasible for larger scale applications, but if you just want a simple log in/log out user authentication model, using a gem as large as Devise is overkill.

This tutorial will explain how to create users and authentication from scratch.

First you need to add the bycrypt gem to your gem file:

gem 'bcrypt', '~> 3.1', '>= 3.1.11'

Then you need to run bundle install.

Next we need to generate a resource, which is similar to a scaffold, but with less automatically generated code:

rails g resource user email password_digest

Next inside the user.rb model add the lines:

has_secure_password

validates_uniqueness_of :email

Inside the users_controller.rb add the following:

def new
    @user = User.new
end

def create
    @user = User.new(user_params)
    if @user.save
        session[:user_id] = @user.id
        redirect_to root_url, notice: "Signed Up Successfully"
    else
        render "new"
    end
end

private

def user_params
  params.require(:user).permit(:email, :password, :password_confirmation)
end

This is the logic behind creating a user.

Inside the views/users/new.html.erb add the following:

<div>
    <div>
        <%= form_for @user do |f| %>
        <% if @user.errors.any? %>
            <div class="error_messages">
                <h2>Form is invalid</h2>
                <ul>
                    <% @user.errors.full_messages.each do |message| %>
                    <li><%= message %></li>
                    <% end %>
                </ul>
            </div>
        <% end %>

        <%= f.label :email %>
        <%= f.text_field :email %>
        <%= f.label :password %>
        <%= f.password_field :password %>
        <%= f.label :password_confirmation %>
        <%= f.password_field :password_confirmation %>

        <%= f.submit %>
        <% end %>
    </div>
</div>

Next we need to create a views/sessions folder, and inside that folder a new.html.erb file. Inside this file is where the user will log in:

<div>
    <div>
    <%= form_tag sessions_path do %>
        <%= label_tag :email %>
        <%= text_field_tag :email, params[:email] %>
        <%= label_tag :password %>
        <%= password_field_tag :password %>
        <%= submit_tag "Log in" %>
        <% end %>
    </div>
</div>

Then we need to create a sessions_controller.rb which will handle the user session:

class SessionsController < ApplicationController
  def new
  end

  def create
    user = User.find_by_email(params[:email])
    if user && user.authenticate(params[:password])
        session[:user_id] = user.id
        redirect_to root_path
    else
        render "new"
    end
  end

  def destroy
    session[:user_id] = nil
    redirect_to root_path
  end
end

In config/routes.rb add resources for both users and sessions as well as custom routes for the log in, log out and sign up routes:

get 'signup', to: 'users#new'
get 'login', to: 'sessions#new'
get 'logout', to: 'sessions#destroy'

resources :sessions
resources :users

Now inside the application_controller.rb we will create two private methods. One to control the current user, and one to authorize what the current user can do:

private

def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
end

helper_method :current_user

def authorize
    redirect_to root_path if current_user.nil?
end

The authorize method can be used in any controller to restrict what the user can access, for example if you didn't want the user to create, edit or destroy something you could put the following at the top of a controller:

before_filter :authorize, only: [:new, :create, :edit, :update, :destroy]

The current_user method can be used inside views which will be demonstrated below.

Inside the application.html.erb file add the following lines so the user can log in, log out or sign up:

# Current_user method
<% if current_user %>
    <%= link_to "Log Out", logout_path %>
    Logged in as: <%= current_user.email %>
<% else %>
    <%= link_to "Log In", login_path %>
    <%= link_to "Sign Up", signup_path %>
<% end %>

If you go to localhost:3000/signup you now should be able to sign a user up, log out and log in.



Last post: March 16, 2017 :: © bytcode 2017 :: contact bitcode.com(at)gmail.com