1

Referring to an article: devise limit one session per user at a time

I have setup my Rails app as follows:

routes.rb

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

Application Controller:

  before_filter :check_concurrent_session

  def check_concurrent_session
    if is_already_logged_in?
      sign_out_and_redirect(current_user)
    end
  end

  def is_already_logged_in?
    current_user && !(session[:token] == current_user.login_token)
  end

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
  end
end

When I wire this up and restart my Rails server it loads fine. However when attempting to login it quickly reverts to the login screen. Per my dev log I can see it hitting the MySessions controller:

Started GET "/users/sign_in" for 127.0.0.1 at 2012-08-30 10:51:24 -0500
Processing by MySessionsController#new as HTML
  Rendered devise/sessions/new.html.erb within layouts/application (1.4ms)
Completed 200 OK in 16ms (Views: 15.8ms | ActiveRecord: 0.0ms)

Devise/Sessions/new

<h2>Secure Login</h2>


<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
  <div><%= f.label :login %>
  <%= f.text_field :login, :placeholder => 'Username or Email' %></div><br />

  <div><%= f.label :password %>
  <%= f.password_field :password, :placeholder => '••••••••' %></div><br />

  <div><%= f.submit "Login", :class => 'btn btn-inverse' %></div>
<% end %>

Even though it's hitting the override controller it's not doing anything after that. I've followed the article to a tee and it worked for another user. Can anyone look at my code and see what I'm doing wrong.

I'd really like to session limit properly as my app depends on it. I've tried using Devise Security Extension but keep getting an undefined method "unique_session_id" after following the instructions so I figured I'd try this out instead.

Thanks in advance, guys!

Community
  • 1
  • 1
nulltek
  • 3,247
  • 9
  • 44
  • 94

1 Answers1

1

Won't

current_user && !(session[:token] == current_user.login_token)

always be true if you're logged in?

Which would explain the redirect since when you re-login, you're logged in so you need to login, repeat.

John Paul Ashenfelter
  • 3,135
  • 1
  • 22
  • 29
  • This behavior occurs when I'm logged out. When I pull up PG and look for the login_token it's blank. That's the part that's not making sense to me. It should be writing a token. This also occurs for new users who haven't logged in yet. Do you have a better method to refactor the code you mentioned? – nulltek Aug 30 '12 at 16:21
  • Depends a bit on the details -- I'd think about writing the "lock" on the account that says someone is logged in to something that is browser independent -- redis, the Rails cache, the db -- and just block the initial login. But that messes with Devise which gets pretty gnarly. – John Paul Ashenfelter Aug 30 '12 at 17:39
  • I was able to get it to work by setting current_user.save(validate: false) which blocks the Devise validations. Also login_token was not set for attr_accessible in the User model. – nulltek Aug 30 '12 at 18:37