Manipulating Sessions in Warden/Devise
As it turns out the best way to set extra sessions stuff or cookies when you use devise is through a method hook provided by warden.
Warden provides 2 hooks that are very useful: after_set_user and before_logout. In a rails app you would put these hooks in an initializer in config/initializers/<yourfile>.rb.
The hook looks like this:
Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
if record && warden.authenticated?(options[:scope])
#... your magic
end
end
Within the block the 3 parameters yielded are:
- record => current resource, most likely a user object,
- warden => an instance of warden::proxy
- options => a series of options like the scope of this login (user,admin,author,moderator,etc)
The object warden has access through pretty much anything, session data, env data, cookies, strategies etc.
- warden.cookies #=> a cookie jar like object that acts just like rails cookies
- warden.session #=> warden specific session data stored in “warden.user.#{scope}.session”
- warden.manager #=> to access a bunch of more stuff that is warden specific
- warden.env #=> pretty much anything else you want to reach into
The thing that surprised me was that warden.session is stored inside a key (“warden.user.#{scope}.session”) inside the main session object. So how do you manipulate the main session object?
The answer happens to be simple: warden.env['rack.session'] will bring back everything in the session.
{"_csrf_token"=>"#{token}",
"warden.user.#{scope}.key"=>
["#{resource.class}", ["#{resource.to_key}"], "#{resource.salt}"],
"warden.user.#{scope}.session"=>
... anything that you set through warden.session[key] => value ...
}
And you manipulate it as you would expect warden.env['rack.session']['foo'] = ‘bar’
For more info on callbacks https://github.com/hassox/warden/wiki/Callbacks
