ankane/pretender

Hooking into devise 2.0.5 and rails 3.2

cobbr2 opened this issue · 1 comments

I've had two problems with hooking pretender into our application.

First, just putting the impersonates :user call into our ApplicationController did not work. We got 'undefined method "current_user"' when we did so. That's because Devise hasn't actually defined that method yet; it's defined when the ActiveSupport.on_load hook is called for ApplicationController, which is later in the Rails startup lifecycle. We've worked around that using:

def current_user
    super
end

Secondly, the Very Important thing (calling stop_impersonating_user before logout) appears to be both more difficult than documented, and unnecessary in our environment. We're using cookie-based (not database-backed) sessions.

Devise provides its own Devise::SessionsController; subclassing it is possible, but requires bringing its views into our own application (note also that it does not provide a logout method; instead, it has a destroy).

Since the session appears to be completely destroyed by Devise's destroy method (and Warden's session handling), I'm wondering what risks might be posed by not calling stop_impersonating_user.

Less directly, we looked at hooking at Warden's before_logout callback, but that does not provide the controller object, so makes direct use of stop_impersonating_user impossible.

We've not encountered the "Security warning" exception in practice while testing.

Am I taking any risks by not calling stop_impersonating_user before logout?

Hey, so sorry, thought I had responded to this earlier.

First issue - I'll have to dig into it more. May make sense to move the hook into a Railtie.

Second issue - To see if there's a security risk, try this:

  1. Impersonate a user
  2. Sign out
  3. Sign in as a different user, and see if you're still impersonating

As far as I know, Devise does not destroy the entire session - just the Devise data.

If it is an issue, here's how to hook into Devise.

Assuming a User model, change this in your routes.

devise_for :users, controllers: {sessions: "sessions"}

Then create a SessionsController with:

class SessionsController < Devise::SessionsController
  def destroy
    stop_impersonating_user
    super
  end
end

Again, sorry for the slow response.