Search code examples
ruby-on-railsrubydevisewarden

Reseting session based on user agent and/or ip change. Rails with Devise


I would like to reset session whenever user agent and/or user ip changes. Project uses Rails with Devise for authentication, CanCanCan for authorisation.

My approach is:

class ApplicationController < ActionController::Base

  before_action :authorize_ip

  def authorize_ip
    if warden.authenticated?
      warden.session['ip'] ||= request.ip
      warden.session['user_agent'] ||= request.user_agent
      warden.logout if warden.session['ip'] != 'request.ip' &&
        warden.session['user_agent'] != request.user_agent
    end
  end
end

From my understanding, it should set warden.session['ip'] and user_agent once and then for following requests whenever request['ip'] or user_agent changes, session should be dropped and User should be logged out. However, when tested with different browsers, warden.session['user_agent'] changes according to what browser I use. I suppose I'm misunderstanding something. Also, if there is a better approach to this problem, please share.

Thanks!


Solution

  • I've solved the issue by adding this to initializers/devise.rb

      Warden::Manager.after_authentication do |_user, auth, _opts|
        auth.raw_session['warden.user.ip'] = auth.request.ip
        auth.raw_session['warden.user.user_agent'] = auth.request.user_agent
      end
    

    and this to application controller:

    class ApplicationController < ActionController::Base
    
      before_action :authorize_ip_user_agent
    
      protected
    
      def authorize_ip_user_agent
        return true unless session['warden.user.ip']
        warden.logout if session['warden.user.ip'] != request.ip &&
          session['warden.user.user_agent'] != request.user_agent
      end
    end