I often want to clear the session store in Rails, in particular, the default cookie-based session store. Some sites seem to suggest that
rake tmp:sessions:clear
accomplishes this task, but it appears that it does not. What is the proper way to clear the cookie-based session store?
If you use Cookie based sessions
You can change the secret_token of your rails app. This will invalidate all existing sessions.
rake secret
Then copy the value in to
RAILS_ROOT/config/initializers/session_store.rb
Thats it. Remember to restart your app after this ;)
If you use database based sessions
rake db:sessions:clear
If you use file based sessions
rake tmp:sessions:clear
The problem is that cookies are client side. Running a rake task on your server won't delete cookies on all the machines that have visited the web page, obviously.
Perhaps you can use session.clear in your controllers somehow? You're right about changing the cookie key, though. Doing so would invalidate any session belonging to the old key. You would have to rescue from ActionController::StaleSession (or something like that), but it'd work.
Change the name of the session cookie. It won't delete the old cookies, but it'll force everyone to get a new session cookie.
It occurs to me now that what I want may not be possible depending on how the cookie-based store is implemented. If the cookies contain all the information the server needs (including a signature for data integrity) then the server does not need to store any information on its side therefore there is no way to invalidate existing cookies. I had assumed the cookie contained some key that corresponded to data on the server-side in order to verify that the cookie is valid, but now I realize this may not be the case.
If this is true, then the only way to clear cookies would be to change the server-side cookie secret used for signing and then presumably restart the server process.
If you are running this on a production server I recommend:
rake secret
Which is simply generating a random secure token. The rake task is basically doing this, which you could do in a console.
SecureRandom.hex(64)
Never check the production key into version control / GIT but use an environment variable instead. So in your config/secrets.yml file use something like:
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
Related
I am working on a legacy Rails 3.2 app and would like to log everybody out and have their _app_session be reset with the secure flag set to true. It seems like either changing our session_store strategy to secure: true or config.force_ssl = true. Strangely only the latter seems to work correctly in Chrome.
The question is that it seems like the best way to log everyone one would be to remove their session variable and I tried this solution here https://stackoverflow.com/a/11422931/152825 of:
rake tmp:sessions:clear
but it didn't seem to work. Is there a better way to clear these session variables?
As far as your sessions are not really saved on backend you can not just delete them. But you can invalidate by changing the secret_key_base.
Rails uses that long random key to encrypt the session cookies. Once it will change
- all the old sessions will no longer be valid, because rails will not be able to decrypt them.
In rails we have something called secret_key_base in config/secrets.yml
What if this production secret is accidentally shared via GitHub (public repo)
What's the worst thing a hacker can do?
Can salted passwords in the users table leak as a result...
Rails by default uses browser cookies as its session store. This means that as opposed to the traditional way of storing session data on the server and only a session id in the cookie, Rails stores the whole session data in the cookie.
This of course would not be very secure in many cases, any user could just see and modify his session contents. So the cookie in Rails is encrypted and signed. The key used for this (encryption and integrity verification) is in secret_key_base.
What this practically means is if this secret_key_base is compromised, any user can decrypt, modify and reencrypt his session cookie (all the data in the session). In some applications this causes no problem as there is nothing interesting stored in the session anyway. But in most cases, it leads to all kinds of problems depending on the actual business logic. For example if privileges were stored in the session, a user could change his privileges in the application, probably an unintended result.
Note that if you use a different session store (like for example Redis), you don't need this secret. Afaik it's only used to encrypt cookies if the cookie store is used for sessions. Using a server-side session store is a good idea and the best practice anyway as it is more secure.
While we were using FileStore as cache store and DalliStore as session store, we could run Rails.cache.clear and it would simply clear the cache with no problems in Sessions whatsoever.
Now that we moved the cache store to mem_cache_store, if we run Rails.cache.clear we clear the cache but also sign out every user, destroying all sessions.
Is this the intended behavior?
#phoet was right on. In my initializers/session_store, config.session_store was set to CacheStore. That's not the default in Rails 4, which is :cookie_store.
What is confusing (and now I see the light) is this: no matter what cache store mecanism you choose, there will always be a cookie stored in the browser (with the name you set in that same file, right after the store mecanism, in the key: 'xxx' option - this key is actually the cookie name and has nothing to do with the key you set in secrets.yml to encrypt it).
If you use the default store mecanism (:cookie_store), the entire "session hash" will be stored in the cookie, and nothing on the server (database/memcached). Everything will be read and written directly in that cookie (which starting in Rails 4 is always encrypted if you set secret_key_base).
If you use any other storage (like CacheStore or ActiveRecordStore), the cookie will still be there, with the same name you set in the 'key' option, BUT it if you decoded it (you need the secret_key_base for that, google for decoding rails 4 session) you'll see will only contain the session ID, and then Rails will look for the data corresponding to that session either in the database (ActiveRecord) or memcached (CacheStore, considering you are using memcached and not FileStore for storing cache, but that's another config).
So, since my session store was set to CacheStore, when I did Rails.cache.clear the cookie wasn't being deleted (that's on the client side of course), but when Rails got the session ID inside that cookie it couldn't find anything in memcached to match it with.
I'm quite confused what is secret_token used for in Rails. Can anyone explain what it is used for? Is it OK to put this token in a public source repository and use it in production, or I should change it before deploying my app to prevent some kinds of attacks?
Answering my own question - secret_token is used to prevent cookie tampering in Rails. Every cookie has a checksum saved with it, so users won't modify cookie contents (and change saved user id to steal someone's account, for example). The checksum is based on cookie contents and secret_token, so if you are using cookie based sessions you should always make sure your secret_token is really secret, otherwise you can't trust that anything you put into session came back unchanged.
I am running Rails 3 configured to use memcached for session store. I have the following setup:
development.rb
config.cache_store = :mem_cache_store
session_store.rb
Foo::Application.config.session_store :mem_cache_store, :key => '_foo_session'
I can start the app fine, when I go to any page I get the following error:
ArgumentError (key too long "rack:session:__really_long_session_key__"):
I realize the limit on memcached key is 255. How can I get around this, or am I doing something wrong?
You're almost certainly seeing this because you're switching from the cookie store to memcached. Your browser still has the old session cookie, with the long ID. You need to delete this cookie from your browser and the problem will go away.
If you're switching from cookie store to memcached on a production site, this will be a problem because you don't have control over your user's browsers. You'll probably need to change the session key to avoid problems in this case.
Is it possible you switched from the cookie store or you run other cookie session store apps on the same domain (e.g. localhost)?
In this case the cookie session store is responsible for the huge session_id string (because it actually stores the whole session in it). Just delete your session cookie and you are fine.
If your "key" is more than 255 characters, it sounds like you are doing something wrong. Why is your session key that long? What's wrong with MD5 or SHA1?