[RUBY] Create authentication function in Rails application using devise

Introduction

--devise is a gem that allows you to easily add authentication to your Rails application. devise is a wrapper for Rack middleware called warden, and the actual authentication is done by warden (so if you want to know the implementation details, first implement warden. I think I need to see it). --In the Rails tutorial, the authentication function is created by scratching, but in the actual Rails application, it seems that creating the authentication function using this devise is the de facto standard.

――This time, for my own study, I would like to organize how to use devise to add authentication function to Rails application. The content is almost the same as this article. Xie Xie

--All of the following implementations can be found in this repository.

environment

install devise

1. Edit Gemfile

# Devise
gem 'devise'

2.bundle install

$bundle install

devise settings

1. Execute the following command

$ rails g devise:install
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml
===============================================================================

Depending on your application's configuration some manual setup may be required:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

     * Required for all applications. *

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"
     
     * Not required for API-only Applications *

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

     * Not required for API-only Applications *

  4. You can copy Devise views (for customization) to your app by running:

       rails g devise:views
       
     * Not required *

===============================================================================

Set default URL

config/development.rb


Rails.application.configure do
  ~~Omission~~
  config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
end

Create root page

You can skip this and set any page as the root page.


$rails g controller StaticPages index

route.rb


Rails.application.routes.draw do
  root 'static_pages#index'
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end

Set flash message

Edit app / views / layouts / application.html.erb

<!DOCTYPE html>
<html> 
 <head>
  <title>DeviseRails5</title>
  <%= csrf_meta_tags %>

  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
 </head>
 <body>
  <p class="notice"><%= notice %></p>
  <p class="alert"><%= alert %></p>

  <%= yield %>

 </body> 
</html>

Create a devise view

$ rails g devise:views
invoke  Devise::Generators::SharedViewsGenerator
create    app/views/devise/shared
create    app/views/devise/shared/_error_messages.html.erb
create    app/views/devise/shared/_links.html.erb
invoke  form_for
create    app/views/devise/confirmations
create    app/views/devise/confirmations/new.html.erb
create    app/views/devise/passwords
create    app/views/devise/passwords/edit.html.erb
create    app/views/devise/passwords/new.html.erb
create    app/views/devise/registrations
create    app/views/devise/registrations/edit.html.erb
create    app/views/devise/registrations/new.html.erb
create    app/views/devise/sessions
create    app/views/devise/sessions/new.html.erb
create    app/views/devise/unlocks
create    app/views/devise/unlocks/new.html.erb
invoke  erb
create    app/views/devise/mailer
create    app/views/devise/mailer/confirmation_instructions.html.erb
create    app/views/devise/mailer/email_changed.html.erb
create    app/views/devise/mailer/password_change.html.erb
create    app/views/devise/mailer/reset_password_instructions.html.erb
create    app/views/devise/mailer/unlock_instructions.html.erb

Create User model

rails g devise User

The above command will generate the following migration files.

db/migrate/20200622180124_devise_create_users.rb


# frozen_string_literal: true

class DeviseCreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      # t.integer  :sign_in_count, default: 0, null: false
      # t.datetime :current_sign_in_at
      # t.datetime :last_sign_in_at
      # t.inet     :current_sign_in_ip
      # t.inet     :last_sign_in_ip

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

It seems that database_authenticatable, registerable, recoverable, rememberable and validatable are turned on by default.

app/models/user.rb


class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
end

This time, we will create it with the default, but you can optionally enable any of the 10 modules.

module   Overview                                                       
Database Authenticatable Hash the password and store it in the database to verify the authenticity of the user during sign-in. Authentication can be done with both POST request or HTTP basic authentication.
Omniauthable OmniAuth(https://github.com/omniauth/omniauth)Add support.
Confirmable Send an email with verification instructions to see if your account has already been verified at sign-in.
Recoverable Resets the user's password and sends a reset instruction.
Registerable Process user sign-up through the registration process, allowing users to edit and destroy their account.
Rememberable Manages the generation and clearing of tokens to remember users from stored cookies.
Trackable Keep track of sign-ins, time stamps, and IP addresses..
Timeoutable Expires sessions that have been inactive for the specified time period.
Validatable Provides email and password verification. This is optional and customizable so you can define your own validation.
Lockable Locks the account after the specified number of failed sign-in attempts. Can be unlocked by email or after a specified time period

Perform a migration

$ rake db:migrate

Edit View

Add header

app/views/layouts/application.html.erb

<!DOCTYPE html>
<html> 
 <head>
  <title>DeviseSampleApp</title>
  <%= csrf_meta_tags %>

  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
 </head>
 <body>
 <header>
    <nav>
        <% if user_signed_in? %>
        <%= link_to 'Profile change', edit_user_registration_path %>
        <%= link_to 'Log out', destroy_user_session_path, method: :delete %>
    <% else %>
        <%= link_to 'Sign up', new_user_registration_path %>
        <%= link_to 'Login', new_user_session_path %>
        <% end %>
    </nav>
  </header>
  <p class="notice"><%= notice %></p>
  <p class="alert"><%= alert %></p>

  <%= yield %>

 </body> 
</html>

――When you access the top page, a screen like this is generated. スクリーンショット 2020-06-23 3.48.36.png

--Click sign up スクリーンショット 2020-06-23 3.34.51.png

――When you signed up and entered your email address and password, you were able to log in successfully! スクリーンショット 2020-06-23 3.35.29.png

Other

Helper methods provided by devise

user_signed_in?

You can check if the user is logged in.

current_user

You can access the logged-in user.

user_session

You can access the session.

Change redirect destination after signing up

app/controllers/application_controller.rb


class ApplicationController < ActionController::Base
  def after_sign_up_path_for(resource)
    edit_user_registration_path #You can edit here and jump to any page
  end
end

After signing up, I am now redirected to the following page.

スクリーンショット 2020-06-23 3.34.18.png

Change redirect destination after login

app/controllers/application_controller.rb


class ApplicationController < ActionController::Base
  def after_sign_in_path_for(resource)
    edit_user_registration_path #You can edit here and jump to any page
  end
end

Callback function

(I'm not sure exactly here)

--It seems that after_fetch is the only callback that devise calls (citation needed), so if you want to call other callbacks, use warden interface. Must be called directly.

References

Recommended Posts

Create authentication function in Rails application using devise
[Implementation procedure] Create a user authentication function using sorcery in Rails
Implement application function in Rails
[Rails] Create an evaluation function using raty.js
[Rails] Function restrictions in devise (login / logout)
Implementation of user authentication function using devise (2)
Creating a user authentication function using devise
Implementation of user authentication function using devise (1)
Implementation of user authentication function using devise (3)
[Rails] Implementation of new registration function in wizard format using devise
Nuxt.js × Create an application in Rails API mode
Implement star rating function using Raty in Rails6
[Rails] Implementation of retweet function in SNS application
[Note] Summary of rails login function using devise ①
[Rails] Create an application
Implement post search function in Rails application (where method)
Rails application guest login function implemented (devise not used)
[Rails] Google, Twitter, Facebook authentication using Devise and Omniauth
Create a login authentication screen using the session function
Search function using [rails] ransack
SNS authentication using Rails google
Implement follow function in Rails
Japaneseize using i18n with Rails
Implement LTI authentication in Rails
Ajax bookmark function using Rails
Memorandum [Rails] User authentication Devise
Implement user registration function and corporate registration function separately in Rails devise
[Rails] Implement community membership application / approval function using many-to-many associations
[Rails] Session timeout setting in devise
Add a search function in Rails.
Preparing to create a Rails application
[rails] Login screen implementation in devise
[Rails] Tag management function (using acts-as-taggable-on)
[Rails] Unexpected validation error in devise
Create pagination function with Rails Kaminari
Implement simple login function in Rails
Create a new app in Rails
Create a filtering function using acts-as-taggable-on
Create My Page with Rails devise
Implement CSV download function in Rails
Let's create a TODO application in Java 4 Implementation of posting function
Let's create a TODO application in Java 6 Implementation of search function
[Rails] Sign-up function using devise error number of arguments (given 0, expected 1)
Let's create a TODO application in Java 8 Implementation of editing function
Install Rails in the development environment and create a new application
How to create a query using variables in GraphQL [Using Ruby on Rails]
Authentication function in Play Framework [Access restrictions]
Introduce two-factor authentication to your Rails application
[Rails withdrawal] Create a simple withdrawal function with rails
ERRORCODE = -4471 occurs in Java application using Db2.
[Rails 6] Register and log in with Devise + SNS authentication (multiple links allowed)
Implemented follow function in Rails (Ajax communication)
[Rails] devise
Create a SPA with authentication function with Rails API mode + devise_token_auth + Vue.js 3 (Rails edition)
Beginners create portfolio in Ruby on Rails
Implement button transitions using link_to in Rails
Multiple image upload function using Rails Carrierwave
Create a login function using Swift's Optional
# 6 show, create implementation to build bulletin board API with authentication authorization in Rails 6
[Rails / JavaScript / Ajax] I tried to create a like function in two ways.
A memo to simply create a form using only HTML and CSS in Rails 6