Posted 5 months ago. Visible to the public. Repeats.

Devise: Invalidating all sessions for a user

Background information about session storage in Rails

Rails has a default mechanism to store the session in the CookieStore. This is a cookie which holds the entire user session hash in the browser. This cookie is serialized, encoded with base64, and signed.

How Devise handles authentication

Devise uses this CookieStore. To track a users session, a salt is stored in the session cookie when a user logs in.
When a user logs out this CookieStore is overwritten and current_user is set to nil.

But what about the old session cookie?

This session cookie is still valid! If this cookie is stolen before it gets overwritten, it can be reused to get access to the application again.

How can we invalidate old session cookies on logout with Devise?

1) Reset password

The only option provided per default by Devise is to change the password of a user. The salt stored in the session cookie by Devise relies on the password. So if you want to logout a user AND invalidate old session cookies you need to reset her password.

2) Extend the salt with a token

Add a session_token column to your devise model (e.g. User) and overwride Devise #authenticatable_salt method to contain your session token:

Copy
class User < ApplicationRecord devise :database_authenticatable, :recoverable, :rememberable def authenticatable_salt "#{super}#{session_token}" end def invalidate_all_sessions! self.session_token = SecureRandom.hex end ... end

You can now invalidate the session cookie by resetting the session_token of a user, when she logs out:

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

Note that changing the session_token will invalidate all session cookies of this user. If she is logged in on other devises (e.g. tablet, mobile phone, …) she will be logged out on all of them.

3) Switch to a persisted storage for sessions on the server

Another option to prevent this session replay attack is to switch to persisted storage for sessions. Therefore you can use either a database, memcache or redis. (e.g. with ActiveRecord::SessionStore)
But this means, you need to take care of adding, accessing, and removing the session data. This may has an impact on performance on high traffic sites since a session may be allocated even for anonymous browsing traffic.

By refactoring problematic code and creating automated tests, makandra can vastly improve the maintainability of your Rails application.

Owner of this card:

Avatar
Natalie Krehan
Last edit:
4 months ago
by Henning Koch
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Natalie Krehan to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more