Devise limit one session per user at a time Devise limit one session per user at a time ruby-on-rails ruby-on-rails

Devise limit one session per user at a time


This gem works well: https://github.com/devise-security/devise-security

Add to Gemfile

gem 'devise-security'

after bundle install

rails generate devise_security:install

Then run

rails g migration AddSessionLimitableToUsers unique_session_id

Edit the migration file

class AddSessionLimitableToUsers < ActiveRecord::Migration  def change    add_column :users, :unique_session_id, :string, limit: 20  endend

Then run

rake db:migrate

Edit your app/models/user.rb file

class User < ActiveRecord::Base  devise :session_limitable # other devise options  ... rest of file ...end

Done. Now logging in from another browser will kill any previous sessions. The gem actual notifies the user that he is about to kill a current session before logging in.


You can't do it.

  • You can control IP addresses of user, so you can prevent presence of user from two IP at a time. ANd you can bind login and IP. You can try to check cities and other geolocation data through IP to block user.
  • You can set cookies to control something else.

But none of this will guarantee that only one user uses this login, and that those 105 IP from all over the world doesn't belong to only one unique user, which uses Proxy or whatever.

And the last: you never need this in the Internet.

UPD

However, what I'm asking is about limiting multiple users from using the same account simultaneously which I feel should be possible

So you can store some token, that will contain some encrypted data: IP + secret string + user agent + user browser version + user OS + any other personal info: encrypt(IP + "some secret string" + request.user_agent + ...). And then you can set a session or cookie with that token. And with each request you can fetch it: if user is the same? Is he using the same browser and the same browser version from the same OS etc.

Also you can use dynamic tokens: you change token each request, so only one user could use system per session, because each request token will be changed, another user will be logged out as far as his token will be expired.


This is how I solved the duplicate session problem.

routes.rb

  devise_for :users, :controllers => { :sessions => "my_sessions" }

my_sessions controller

class MySessionsController < Devise::SessionsController  skip_before_filter :check_concurrent_session  def create    super    set_login_token  end  private  def set_login_token    token = Devise.friendly_token    session[:token] = token    current_user.login_token = token    current_user.save(validate: false)  endend

application_controller

  def check_concurrent_session    if duplicate_session?      sign_out_and_redirect(current_user)      flash[:notice] = "Duplicate Login Detected"    end  end  def duplicate_session?    user_signed_in? && (current_user.login_token != session[:token])  end

User modelAdd a string field via a migration named login_token

This overrides the default Devise Session controller but inherits from it as well. On a new session a login session token is created and stored in login_token on the User model. In the application controller we call check_concurrent_session which signs out and redirects the current_user after calling the duplicate_session? function.

It's not the cleanest way to go about it, but it definitely works.