Devise Authentication with Rails 5

Devise is the cornerstone gem for Ruby on Rails authentication. With Devise, creating a User that can log in and out of your application is so simple because Devise takes care of all the controllers necessary for user creation (users_controller) and for user sessions (users_sessions_controller). The gem is based on Warden and handles authentication with bcrypt, eliminating the need to hash and salt passwords manually (trust me, this is so useful. when I was starting out as a developer this sent me down so many rabbit holes..).

There is really no reason to not use an authentication gem when you’re working with RoR. Authentication by hand is messy and requires multiple controllers and several hours of setup (not including testing, you ARE including tests in your application, right?). If you are curious about how Devise works under the hood, my suggestion is to go through a manual tutorial to understand the basics of authentication, build a test Rails app that uses manual authentication, read about the principles, then never do it again (unless your company makes you do it in the future).

This isn’t an overview of setting up Devise (you can find that in the Devise gem wiki). In this post, I wanted to go over some of the gem’s advantages, features, and a few drawbacks (and how to work around them!)

Using Devise with your model

Devise uses 10 modules to configure user authentication. You can find these modules inside of your user model. Six of these modules are enabled by default (marked with an *). Modify existing configuration in the config/initializers/devise.rb file.

  • *Database Authenticable – Hashes and stores the password in database. Authentication is done by a POST request. Necessary to save user/hashed password in the DB.
  • Omniauthable – Adds support for Omniauth provider, allowing log in through third-party providers like Facebook, Twitter, etc
  • Confirmable – Disables access to the user account unless a user has confirmed their account through email.
  • *Recoverable – Adds a ‘Forgot my Password’ link that allows the user to reset their password using email
  • *Registerable – Creates a registration process, users can now edit and delete their account. Disable for beta testing/invitation-only sites
  • *Rememberable – Creates a token and stores a user session with a saved cookie (adds REMEMBER ME checkbox)
  • *Trackable – Tracks user IP addresses, sign in count, last sign in, and timestamps
  • Timeoutable – Logs a user out after a certain amount of time.
  • *Validatable – Uses built-in Devise validations for email address and password (length, characters, etc). Change validations in config/initializers/devise.rb
  • Lockable – Locks an account after a specific amount of time or specific amount of log in attempts.

Devise Helper Methods

Devise also comes with

  • before_action :authenticate_user! –  Add to any controller to limit access to an action unless a user is logged in
    before_action :authenticate_user!, except: [:show, :index]
    before_action :authenticate_user!, only: [:show, :index]
  • skip_before_action :authenticate_user! –  Alternatively, you can add the before action to the application controller to black-list every page in the application, then use the skip_before_action command to allow access page-by-page
     skip_before_action :authenticate_user!, except: [:show, :index]
     skip_before_action :authenticate_user!, only: [:show, :index]
  • user_signed_in? – Verifies if the user is signed in before a certain action can be executed. Add to controller or view. Returns true or false.
    if user_signed_in?
     DO SOME ACTION
     else
     DO ANOTHER ACTION
     end
  • current_user_ – Add to controller or view to return an instance of the user performing the action. E.x. You are creating a restaurant that belongs to a user. Set @restaurant.user to current_user if the current user is the owner of the restaurant
     @restaurant.user = current_user
     @restaurant.save

Routes

You do not need to set up individual routes if you’re using Devise, just add one of the following lines to your config/routes.rb file:

devise_for :users
devise_for :MODELNAME (if not using User as the name of the model)

 

Where Devise fails

By default, the use of Devise doesn’t enforce strong passwords. The good thing about the gem is that it doesn’t store the password – just an encrypted hash – but that still allows users to create passwords like ‘123456’ or ‘password’. My rule of thumb is that if users can create unsafe passwords, they will create unsafe passwords.

  • To enable strong passwords, make sure to add the Devise Security Extension gem (there are requests to include it in the Devise core, but who knows when that will happen
  • Read more about securing Devise at DuckType Labs.

 

Last updated February 5, 2018

 

This is a work in progress that I will keep updating. Did I miss anything about Devise that you’d like to know about further? Let me know below! 


Also published on Medium.

Leave a Reply