Nick Hammond

Software Developer, Cyclist, & Traveler.

Authlogic and automatic logouts

In rails

I recently added in a timed automatic logout to an application that pays attention to user interaction as well as Authlogic's lastrequestat magic field. If you just need the user to be automatically logged out after 15 minutes and it's ok to have them kicked out on the next request then the native functionality within Authlogic will work great, take a look at the Authlogic::Session::Timeout section in the documentation.

What I needed was for the logout functionality to pay attention to mouse and key interactions. We didn't want the user to be filling out a long description and then go to save the record and the user get kicked out because it took them more than X amount of time to complete it.

The way I set it up is we are running a Javascript timer on the frontend as well as I've enabled Authlogic's logoutontimeout functionality. I couldn't rely on just the Javascript timer because I have to assume that our user might have multiple tabs open so the timer could timeout on one tab. The only thing this method doesn't support is if the user has two tabs open and is only activating keypress/mouse movement, if they are making new requests then it relies on Authlogic appropriately. It's an edge case but it's a possibility.

Alright, first we should setup Authlogic's timeout functionality.


class UserSessionsController < ApplicationController

  def timeout
    if Rails.env.development?
      logout = false
    else
      logout = current_user_session.stale?
    end

    respond_to do |format|
      format.json { render :json => logout}
    end
  end

  # Authlogic attempts to call this method within your 
  # controller, you can define whatever you'd like in here to 
  # not track the last_request_at. We need to disable the
  # update of last_request_at for our ajax timeout action 'timeout' 
  # since we would basically be overwriting ourselves. You can
  # put whatever functionality you need in here, it just needs
  # to return true/false.
  def last_request_update_allowed?
    action_name != "timeout"
  end

end


class UserSession < Authlogic::Session::Base
  logout_on_timeout Rails.env.production?
end

I've disabled this on development because it doesn't need to be guarded like the production environment for users.


class User < ActiveRecord::Base
  acts_as_authentic do |c|
    c.logged_in_timeout = 15.minutes
  end
end 

Set this to whatever you would like, this is the value that Authlogic uses to determine when a user session is stale.


var timer;

$(function() {
  set_timeout();
  $(document).bind('mousemove click keypress scroll', reset_timer);
});

function reset_timer() {
  window.clearInterval(timer);
  set_timeout();
}

function set_timeout() {
  timer=setInterval("logout()",1000*15*60); // 15 mins
}

function logout(){
  $.get('/user_session/timeout.json', function(force_logout){
    if (force_logout) {
      window.location = "https://example.com/logout";
    }
  });
}

We initially rely on the Javascript timer but we double check the user session in the background to make sure it's actually stale. This background check is really just to cover the multiple tab scenario.

And of course you need to setup the route to the timeout action


app.resource :user_session, :collection => {:timeout => :get}

I didn't highlight this in the example but you would probably want to give a notice to the user that they are going to be automatically logged out soon. Possibly an alert box or what would be ideal is to push a notice to the user so that they would get it on all of their open tabs.

P.S. We should keep in touch, subscribe below.