Manage active sessions in Rails 2024
Tags: security, pentest
Published: 2024-04-30 12:26:28

---
title: Manage active sessions in Rails 2024
published: true
date: 2024-03-24 00:00:00 UTC
tags: security,pentest
canonical_url: https://blog.corsego.com/secutiry-manage-active-sessions
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wmrx8la69e9worwyqbot.png
---

Ok, so sometimes to enchance security of your application you will want to allow users to see all the devices/browsers they are logged in with. You would also provided a button to sign out of a device/browser.

Here’s how you can do it:

### 1. Store current login (device/browser) info and ensure the current device/browser has not been logged out.

```
rails g resource Login user:references device_id ip_address user_agent


# app/models/user.rb
class User < ApplicationRecord
  has_many :logins, dependent: :destroy
end


# app/models/login.rb
class Login < ApplicationRecord
  belongs_to :user
end


# app/controllers/application_controller.rb
  include Users::LoginActivity

  # ensure this device has not been logged out
  before_action :validate_login, if: :current_user

  # this works with Devise
  # when logging a user in, register the current device
  def after_sign_in_path_for(resource_or_scope)
    set_login # this!
    root_path
  end


# app/controllers/concerns/users/login_activity.rb
module Users
  module LoginActivity
    extend ActiveSupport::Concern

    # included do
    # helper_method :set_login
    # end

    def set_login
      current_login = current_user.logins.where(device_id: device_id).first_or_create(ip_address: request.remote_ip, user_agent: request.user_agent, device_id: device_id)
      # current_login.touch
      # current_login.save
      session[:device_id] = device_id
      # cookies[:device_id] = device_id
    end

    def validate_login
      if Rails.env.test?
        # mock
        current_login = current_user.logins.create(device_id: "test_device_id")
      else
        current_login ||= current_user.logins.find_by(device_id: session[:device_id])
      end

      if current_login.nil?
        sign_out current_user

        flash[:notice] = 'Device not recognized'
        redirect_to new_user_session_path
      end
    end

    private

    def device_id
      Digest::SHA256.hexdigest("#{request.remote_ip}_#{request.user_agent}")
      # SecureRandom.hex
    end

  end
end

```

### 2. Views to see all logins of a user, log out of a select device/browser

```
# config/routes.rb
  namespace :users do
    resources :logins, only: %i[index destroy]
  end


# app/controllers/users/logins_controller.rb
class Users::LoginsController < Accounts::BaseController
  def index
    @logins = current_user.logins
  end

  def destroy
    @login = current_user.logins.find(params[:id])
    @login.destroy

    flash[:notice] = "You have been logged out of this device."
    redirect_to edit_user_registration_path
  end
end


# app/views/logins/index.html.erb
<% @logins.order(updated_at: :desc).each do |login| %>
  <div>
    <i class="<%= device_type_icon(login.user_agent) %>"></i>

    <%= device_description(login.user_agent) %>

    Last login at:
    <%= login.updated_at %>

    IP address:
    <%= login.ip_address %>

    <% if login.device_id == session[:device_id] %>
      current session
    <% else %>
      <%= link_to 'Disconnect', users_login_path(login), method: :delete %>
    <% end %>

  </div>
<% end %>

```

ℹ️ [gem “device\_detector”](https://github.com/podigee/device_detector) will help you decript `user_agent` info and make it user-friendly.

```
module LoginsHelper
  def device_description(user_agent)
    device = DeviceDetector.new(user_agent)
    "#{device.name} / #{device.os_name}"
  end

  def device_type_icon(user_agent)
    device = DeviceDetector.new(user_agent)

    case device.device_type
    when "tablet"
      "fa fa-tablet"
    when "smartphone"
      "fa fa-phone"
    when "desktop"
      "fa fa-desktop"
    end
  end
end

```

That’s it! 🤗

Inspired by:

- [vitobotta - Manage active sessions in Rails](https://vitobotta.com/2016/10/19/manage-active-sessions-)
- [adamcooke/authie](https://github.com/adamcooke/authie)