Stop Devise from clearing session
Solution 1:
In the lasts versions of devise it is not necesary to override the sessions controller, instead you can just use:
config.sign_out_all_scopes = false
In the devise.rb
file to get the desired behaviour.
Solution 2:
The destroy
¹ method of SessionsController
contains the following line:
signed_out = Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
The sign_out_all_scopes
² method calls warden.logout
without any arguments, and the sign_out
³ method calls warden.logout(scope)
.
The documentation of the logout
⁴ method states:
# Logout everyone and clear the session env['warden'].logout # Logout the default user but leave the rest of the session alone env['warden'].logout(:default)
Conclusion: sign_out
should preserve the session when given a specific scope. However, I don't see any way to do that. sign_out_all_scopes
is always called first, and will only return false
if it couldn't log any user out.
I recommend either posting a feature request on their issue tracker or developing your own authentication solution. Rails now provides has_secure_password
, and these days people seem to be going for the latter in order to avoid running into these problems.
¹ Devise::SessionsController#destroy
² Devise::Controllers::Helpers#sign_out_all_scopes
³ Devise::Controllers::Helpers#sign_out
⁴ Warden::Proxy#logout
Solution 3:
You could just override Devise's SessionController, like I did to preserve a shopping cart:
sessions_controller.rb
class SessionsController < Devise::SessionsController
def destroy
order_id = session[:order_id]
super
session[:order_id] = order_id
end
end
routes.rb
devise_for :users, :controllers => { :sessions => "sessions" }
Solution 4:
In addition to Mattheus. The statement
signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
is perhaps the best general log out statement, considering the possibility of being signed in with multiple roles. If, for you case, your user is just signed in as one role, and you want to preserve the rest of the session on signout, the easiest way is to do:
$ git clone git://github.com/plataformatec/devise.git
$ cd devise
$ git branch my_devise
$ git checkout my_devise
Open app/controllers/devise/sessions_controller.rb in your editor. In the method destroy, replace
signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
with
signed_out = sign_out(resource_name)
Save and exit editor and do
$ git commit -am "remove only warden data from session on logout, preserve other data."
In the Gemfile of your project, describe the dependency to devise like
gem 'devise', :path => "[YOUR PATH]/devise", :branch => "my_devise"