3

I need to deserialize the session cookie by hand to extract the user from it. The enviroment is rails, though it is not in the http server context, so there is no request for devise to automatically deserialise. There is the Warden::SessionSerializer, though I did not really get how to use it.

Before I wasn't using Devise so I used this method to deserialize the rails session cookie:

def decrypt_cookie(cookie)
  cookie = CGI.unescape(cookie)
  config = Rails.application.config

  encrypted_cookie_salt = config.action_dispatch.encrypted_cookie_salt
  encrypted_signed_cookie_salt = config.action_dispatch.encrypted_signed_cookie_salt

  key_generator = ActiveSupport::KeyGenerator.new(config.secret_key_base, iterations: 1000)
  secret = key_generator.generate_key(encrypted_cookie_salt)
  sign_secret = key_generator.generate_key(encrypted_signed_cookie_salt)

  encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret)
  encryptor.decrypt_and_verify(cookie)
end

Since some people might be skeptical whether there is a context in which manually deserializing the cookie can ever be proper: The client (browser) authenticates via HTTP, and the session is of course stored in the cookie. Rails is also running (rails runner) the websocket server that responds to certain privileged actions. For these I need to (re-)authenticate the user. If someone sees a different (better) way of doing that, I'd be glad to read it. :)

Gregor Weber
  • 690
  • 9
  • 24

3 Answers3

1

The way I describe for deserializing the cookie is just the right way. It is actually the same in Devise, the keys just changed and I jumped to quickly to the conclusion that there must be a different serilization process going on.

Gregor Weber
  • 690
  • 9
  • 24
0

Do you have to use Devise? I posted previously on using Warden to roll your own token auth which you have complete control over. If you decide like me to just do the easy thing and implement auth yourself you will see its easy to lookup a user from a token via your models.

Community
  • 1
  • 1
Andrew Hacking
  • 6,296
  • 31
  • 37
  • yes, thank you, but devise is needed. I write my own confirmation/reset/... logic, but I like the way devise handles it. – Gregor Weber Nov 26 '14 at 02:27
-1

You can access the session object in your controller. What key do you use to store the user_id? You should just be able to do session[:key], so if you store the id as user_id, then session[:user_id].

Bryce
  • 2,802
  • 1
  • 21
  • 46
  • Though I am starting the script as a Rails script (so the general enviroment is loaded), it is not inside of a controller, so devise did none of the deserializing for me. – Gregor Weber Nov 16 '14 at 22:14
  • If you can access the Warden object (I assume you can in your script, given your question), then you can use `#{warden_instance}.request.session` I believe – Bryce Nov 16 '14 at 22:21
  • There is also no request, it is started from a non http context – Gregor Weber Nov 16 '14 at 22:22
  • 2
    If there's no request, how do you have a session? How/when is the session being created? – Bryce Nov 16 '14 at 22:26
  • Well, in another context there is also a running rails http server in which the session is created. But in the context of the script I only have the cookie. – Gregor Weber Nov 16 '14 at 22:29
  • So does your script have access to the secret token that was used to secure the original session cookie? Honestly, it sounds like what you are trying to do is not in keeping with great security practices, so you're going to have to do something kind of hacky. Here's the docs on how rails secures its cookies though. http://api.rubyonrails.org/classes/ActionDispatch/Session/CookieStore.html – Bryce Nov 16 '14 at 22:33
  • Yes, I guess so. Since it is started with the same rails runner as the server and the token should be the one in its config file right? – Gregor Weber Nov 16 '14 at 22:34
  • I guess so? Honestly, I could give you better advice if I understood what you were actually trying to do. This sounds...hacky. Which maybe is the best way to do it, but it doesn't sound like an approach I've taken in any webapp I've ever built. – Bryce Nov 16 '14 at 22:39
  • Okay, if it helps: the script starts a websocket server which gets the cookie in a message from the client. Afaik there is no better way to find out which user sent a socket message – Gregor Weber Nov 16 '14 at 22:41