Img source: interexchange.org

Devise is one of the most famous Ruby gems, which is a flexible authentication solution for Rails based on Warden. It comes with a lot of useful features, but it also has its limitations. One of them is that it does not invalidate a session even though you log out. One of the core developers behind Devise accepts it, and gives the advice of replacing cookie-based storage to address this issue. Fortunately, there is a quicker solution as well.

A recent article published recently mentions a really great way to solve this issue without having to change the cookie-based storage. Devise uses CookieStore, which is a default Rails mechanism for storing the session, and for tracking a user’s session, it stores a salt in the session cookie.

When a user logs out, that particular session is not invalidated. In other words, if you were to copy the session value that is stored in the cookies and use it in another browser, or another machine, you would be able to use that same session.  

Devise suggests asking users to change their passwords, as the salt stored in the session cookie by Devise relies on the password, and changing the password would invalidate the old session.

An easier and more practical solution to this is adding a new column, for example session_token column to your Devise model (usually a User model):

class User < ApplicationRecord

  devise :database_authenticatable, :recoverable, :rememberable
         
  def authenticatable_salt
    "#{super}#{session_token}"
  end

  def invalidate_session!
    self.session_token = SecureRandom.hex
  end
  
  ...
end

Then you need to invalidate the session cookie by resetting the session_token of a user when logging out.



class Users::SessionsController < Devise::SessionsController
  
  def destroy
    current_user.invalidate_session!
    super
  end

end

That’s all what you need to do. Now, when a user logs out, that respective session will be invalidated. Note that this log out from a particular device will also lead to the log out from all other devices, for example in another computer, or smartphone.

The article also goes on to mention that you can invalidate the session by switching to a persisted storage for sessions on the server, by using a database, memcache, or Redis, but this comes with additional changes. You will also need to care of adding, accessing, and removing the session data, which may has an impact on performance on high traffic sites since a session may be allocated even for anonymous browsing traffic.