Diego Scataglini

Looking Ahead

Manipulating Sessions in Warden/Devise

February9

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