Devise
Devise is the most popular authentication gem for Rails. It provides a complete authentication solution with minimal setup.
Installation
ruby
1# Gemfile
2gem 'devise'bash
1bundle install
2rails generate devise:installFollow the setup instructions shown after installation.
Basic Setup
Generate User Model
bash
1rails generate devise User
2rails db:migrateConfigure Routes
ruby
1# config/routes.rb
2Rails.application.routes.draw do
3 devise_for :users
4
5 # Your routes
6 root 'home#index'
7endThis adds routes for:
/users/sign_in- Login/users/sign_up- Registration/users/sign_out- Logout/users/password/new- Forgot password/users/password/edit- Reset password/users/confirmation/new- Resend confirmation/users/edit- Edit profile
Devise Modules
ruby
1# app/models/user.rb
2class User < ApplicationRecord
3 devise :database_authenticatable, # Password authentication
4 :registerable, # User registration
5 :recoverable, # Password reset
6 :rememberable, # Remember me
7 :validatable, # Email/password validations
8 :confirmable, # Email confirmation
9 :lockable, # Lock after failed attempts
10 :timeoutable, # Session timeout
11 :trackable, # Track sign in count, timestamps, IP
12 :omniauthable # OAuth authentication
13endController Helpers
ruby
1# In any controller
2class ArticlesController < ApplicationController
3 before_action :authenticate_user! # Require login
4
5 def index
6 # current_user is available
7 @articles = current_user.articles
8 end
9end
10
11# In views
12<% if user_signed_in? %>
13 Welcome, <%= current_user.email %>
14 <%= link_to "Log out", destroy_user_session_path, method: :delete %>
15<% else %>
16 <%= link_to "Log in", new_user_session_path %>
17 <%= link_to "Sign up", new_user_registration_path %>
18<% end %>Customizing Views
Generate views to customize them:
bash
1rails generate devise:viewsThis creates views in app/views/devise/:
sessions/new.html.erb- Login formregistrations/new.html.erb- Sign up formregistrations/edit.html.erb- Edit profilepasswords/new.html.erb- Forgot passwordpasswords/edit.html.erb- Reset passwordconfirmations/new.html.erb- Resend confirmationmailer/- Email templates
Custom Login Form
erb
1<!-- app/views/devise/sessions/new.html.erb -->
2<h2>Log In</h2>
3
4<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
5 <div class="field">
6 <%= f.label :email %>
7 <%= f.email_field :email, autofocus: true, autocomplete: "email", class: "form-control" %>
8 </div>
9
10 <div class="field">
11 <%= f.label :password %>
12 <%= f.password_field :password, autocomplete: "current-password", class: "form-control" %>
13 </div>
14
15 <% if devise_mapping.rememberable? %>
16 <div class="field">
17 <%= f.check_box :remember_me %>
18 <%= f.label :remember_me %>
19 </div>
20 <% end %>
21
22 <div class="actions">
23 <%= f.submit "Log in", class: "btn btn-primary" %>
24 </div>
25<% end %>
26
27<%= render "devise/shared/links" %>Customizing Controllers
Generate controller to customize:
bash
1rails generate devise:controllers usersruby
1# app/controllers/users/registrations_controller.rb
2class Users::RegistrationsController < Devise::RegistrationsController
3 before_action :configure_permitted_parameters
4
5 protected
6
7 def configure_permitted_parameters
8 devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :username])
9 devise_parameter_sanitizer.permit(:account_update, keys: [:name, :username, :avatar])
10 end
11
12 def after_sign_up_path_for(resource)
13 dashboard_path
14 end
15endUpdate routes:
ruby
1devise_for :users, controllers: {
2 registrations: 'users/registrations',
3 sessions: 'users/sessions'
4}Adding Custom Fields
bash
1rails generate migration AddNameToUsers name:string
2rails db:migrateruby
1# app/controllers/application_controller.rb
2class ApplicationController < ActionController::Base
3 before_action :configure_permitted_parameters, if: :devise_controller?
4
5 protected
6
7 def configure_permitted_parameters
8 devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
9 devise_parameter_sanitizer.permit(:account_update, keys: [:name, :avatar])
10 end
11endConfirmable (Email Verification)
bash
1rails generate migration AddConfirmableToUsers confirmation_token:string:uniq confirmed_at:datetime confirmation_sent_at:datetime unconfirmed_email:string
2rails db:migrateruby
1# app/models/user.rb
2devise :confirmable
3
4# For existing users
5User.update_all(confirmed_at: Time.current)Lockable (Account Locking)
bash
1rails generate migration AddLockableToUsers failed_attempts:integer unlock_token:string:uniq locked_at:datetime
2rails db:migrateruby
1devise :lockable
2
3# config/initializers/devise.rb
4config.lock_strategy = :failed_attempts
5config.unlock_strategy = :both
6config.maximum_attempts = 5
7config.unlock_in = 1.hourOAuth with OmniAuth
ruby
1# Gemfile
2gem 'omniauth-google-oauth2'
3gem 'omniauth-github'
4gem 'omniauth-rails_csrf_protection'ruby
1# config/initializers/devise.rb
2config.omniauth :google_oauth2,
3 ENV['GOOGLE_CLIENT_ID'],
4 ENV['GOOGLE_CLIENT_SECRET'],
5 scope: 'email,profile'
6
7config.omniauth :github,
8 ENV['GITHUB_KEY'],
9 ENV['GITHUB_SECRET'],
10 scope: 'user:email'ruby
1# app/models/user.rb
2devise :omniauthable, omniauth_providers: [:google_oauth2, :github]
3
4def self.from_omniauth(auth)
5 where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
6 user.email = auth.info.email
7 user.password = Devise.friendly_token[0, 20]
8 user.name = auth.info.name
9 end
10endruby
1# app/controllers/users/omniauth_callbacks_controller.rb
2class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
3 def google_oauth2
4 handle_auth("Google")
5 end
6
7 def github
8 handle_auth("Github")
9 end
10
11 private
12
13 def handle_auth(provider)
14 @user = User.from_omniauth(request.env["omniauth.auth"])
15
16 if @user.persisted?
17 sign_in_and_redirect @user, event: :authentication
18 set_flash_message(:notice, :success, kind: provider) if is_navigational_format?
19 else
20 session["devise.auth_data"] = request.env["omniauth.auth"].except(:extra)
21 redirect_to new_user_registration_url
22 end
23 end
24endConfiguration
ruby
1# config/initializers/devise.rb
2Devise.setup do |config|
3 config.mailer_sender = 'noreply@example.com'
4
5 # Password requirements
6 config.password_length = 8..128
7
8 # Session timeout
9 config.timeout_in = 30.minutes
10
11 # Remember me duration
12 config.remember_for = 2.weeks
13
14 # Reset password token validity
15 config.reset_password_within = 6.hours
16
17 # Sign out method
18 config.sign_out_via = :delete
19endDevise provides a robust, battle-tested authentication solution for Rails!
