I'm in the process of upgrading a Rails app from Rails 2 directly to Rails 4. I'm using the new /config/initializers/session_store.rb file, with CookieStore, but for some reason my sessions are not saving.
When trying to do something along the lines of
render :text => "#{request.session_options[:id]}"
I get a new session ID every refresh.
I've tried on different browsers, and all should be accepting cookies.
I have no idea what's going on. Why won't these sessions persist?!
Edit: thank you all for your suggestions. Here's a little more information, and a few things I've noticed:
First, about my set up -- I'm running the server with Rails 4/Ruby 2 through RVM on an Ubuntu VM on my Windows 7 machine.
Although I'm upgrading from Rails 2, that only really applies to the models/controllers/views/etc -- I generated a new Rails 4 application for all of the supporting infrastructure.
I created another application on the same VM that JUST sets a session and then displays, and that works fine.
What the session is storing varies slightly depending on what the user is doing, but usually it holds simply a user id (just an integer), and occasionally a little more -- (i first noticed this manifesting itself while trying to pass an OAuth token from the OAuth gem.)
I've noticed that if the VM's system clock falls behind the Windows 7 host machine clock, the user id sessions hold. That causes other problems, especially with OAuth, but there seems to just be a time issue somewhere. I've tried doing things like removing the time zone from my environments/development.rb, but that did not help.
As a general answer a couple of possible problems are
Session size over 4K limit (which is apparently the case).
CookieOverflow is raised if you attempt to store more than 4K of data.
Please, bear in mind that if you store an object in session, the object is previously serialized before storing it and its size would be bigger. More info on the general problem and possible solutions for the specific problem, here.
Problems with CSRF protection.
If the security token doesn't match what was expected, the session
will be reset
Edit: To check if it is a CSRF case, you can, as Abdo comments below, temporarily disable the protect_from_forgery line in ApplicationController
I had a similar symptoms. It turns out it was because I added the rails-api gem and it totally broke session saving.
From: Railscasts Episode 415 Upgrading to Rails 4
There’s one more configuration change we need to make, in the secret
token initializer. In Rails 4 the configuration option in this file
has been renamed from secret_token to secret_key_base. We’ll need to
specify both options while we’re transitioning from Rails 3 but once
we’ve successfully migrated our application we can remove the
secret_token option. It’s best to use a different token for our
secret_key_base.
This is necessary because we’re moving from a serialized cookie stored
on the client to an encrypted cookie. This prevents users from easily
being able to see the contents of their session cookies.
The episode includes a very good series of tips regarding upgrading from 2 to 4 and I was able to do that successfully using this tutorial.
Related
As far as I know, secret_key_base is only used for signing cookies and changing secret_key_base will cause existing cookies to become invalid. I need to change secret_key_base on production, having existing users logged out is acceptable behavior but I am concerned about possible other side effects. Will the old cookies simply be deleted/replaced when they next visit the website or will they hang around and cause issues? Are there any other changes that will occur other than users being logged out?
The application’s key_generator, and thus secret_key_base, are used by three core features within the Rails framework:
1 Deriving keys for encrypted cookies which are accessible via cookies.encrypted.
2 Deriving the key for HMAC signed cookies which are accessible via cookies.signed.
3 Deriving keys for all of the application’s named message_verifier instances.
you can read more at https://medium.com/#michaeljcoyne/understanding-the-secret-key-base-in-ruby-on-rails-ce2f6f9968a1
The impact of your application by changing the secret_key_base on prod will depend on how many cookies your application depends on. I would say all your clients will have to regenerate their cookies 1 time after that it should be back to normal.
The secret_key_base can be upgraded in a rotating way, with no impact to the users.
I have found a tutorial on how to do this here.
This seems to work, and following this tutorial, I was able to install an automated periodic renew of the secret_key_base, per scheduler, with configurable timespan. Only if users stay inactive for longer than that timespan (e.g. 3 months), their session will become invalid.
This applies to the standard rails functionality of protecting the session-cookie. If your application does other things with the secret_key_base, then you will have to process respective rotations there also.
This question is for a production Grails app using Spring Security configured with BCrypt.
To keep up with increasing server CPU speed, I would like to up the value of the grails.plugin.springsecurity.password.bcrypt.logrounds property so that password hashing takes longer and is less susceptible to attack.
At first thought, I figured this was a daunting task requiring a trickle approach as users logged in or massive re-encoding and custom login handlers, but it appears to work without any other change when trying it locally between runs (with a persistent database, simulating a non-local deploy).
I'm guessing this is because the logrounds is stored on the password hash: when going from 10 to 20 between runs locally, for example, the passwords look as follows
$2a$10$i/PEPcvSj... <-- account created when logrounds was set to 10
'$2a$20$3GGujw6o... <-- account created when logrounds was set to 20
I have tested:
Old accounts created before the change can still log in.
Old accounts can change their password, and the new hashes use the new logrounds setting
New accounts can be created and logged in as expected
Trying to log in with an account that does not exist takes the expected new delay.
Is there any reason not to proceed with the change? The high degree of caution here is because a mistake that prevents production login in any way would be extremely costly
Everything worked as expected, so the answer is that yes, you can. You can change the logrounds without impact to existing accounts as the logrounds used to produce the hash is built into the hash. Nice feature of BCrypt
I'd like to understand what's really going on when signing in a user with rails/devise.
I've created a minimal rails app, installed devise and created a User devise model.
Everything works fine, and when I log in (using remember me) I get a session cookie just as expected.
Now what's bugging me is : How does rails handle the session informations that the browser is passing through the cookie ?
I'd naively expect some information to be stored in the database, but I don't see where. There's no such thing as session table, no session column in Users, and I couldn't find anything of interest in the tmp dir.
Note that restarting the server wouldn't kill my session. It is of course expected, but now I'm really wondering what kind of magic is happening here ?
in other words : how does the server check the validity of a cookie to authenticate a user ?
Thanks !
The default rails session storage is CookieStore. This means that all the session data is stored in a cookie rather than in the database anywhere. In Rails 3.2 the cookie is signed to prevent tampering, but not encrypted. In Rails 4 it's generally encrypted by default. The fact that it's in a cookie is how it persists across restarts of your server. It also means you can only store 4k of data and you wouldn't want to store anything sensitive in there in Rails < 4. It's best to keep a minimum of data in the session anyway.
You can also opt for storing the session data in the database and only having a session id in a cookie.
This answer I gave the other week has some extra info that might be useful:
Sessions made sense to me before I started reading about them online
Also, the rails api doc for CookieStore gives a nice summary:
http://api.rubyonrails.org/classes/ActionDispatch/Session/CookieStore.html
I've got a Rails application running and it seems that every once in a while a user gets the cookie session_id value from a different user.
I use active_record_store to keep track of the session in Rails.
The current_user method:
def current_user
#current_user ||= session[:user_id] ? User.find_by_id(session[:user_id]) : nil
return #current_user
end
I run 8 ruby processes on a Windows machine using Apache 2.2.15. Sometimes it serves the incorrect session_id to the user. My rails version is 2.1.2
In the log file I can see the user changes session_id of a different user.
For instance:
Processing Manage::TruckController#show (for 179.34.103.8 at 2011-05-12 07:35:24) [POST]
Session ID: 1fbc801bbade1007291901ca810bfeda1eab76
....
Completed
And 5 minutes later is would get a different session id, however belonging to a valid user.
Processing Manage::TruckController#edit (for 179.34.103.8 at 2011-05-12 07:40:01) [POST]
Session ID: 2f8e84c40c490c509feabbce9701aa9101ba0f
....
Completed
To me this seems that Rails is handing out incorrect session_id data to the cookie that is stored on the web browser of the user.
Any suggestions on this?
From looking at the code and
the security guide, it seems like there is a slight possibility of MD5 collision. It's very unlikely that this would happen or be reproducible though, so I'm more inclined to say it has something to do with the browser testing.
I'd first make sure that your browser isn't serving up these bad session IDs by using a tool like Charles.
I also recommend using the cookie session whenever possible which would avoid this sort of problem.
Finally, since you're running a fairly old version of Rails it might be worth trying an upgrade. It's possible you're hitting an old bug.
I found this extremely useful.
how-do-i-prevent-rails-users-from-accidentally-authenticating-as-the-wrong-user
If you are:
destroying your database in development
AND
using the out-of-the-box Rails secret_token.rb
The client browser will have preserved a valid session containing a user_id that may or may not belong to that user.
I had a similar issue and resolved it using a code snippet similar to
this comment by mdesantis on managing Rails secret token
is it true that Rails depend on cookies? It seems that flash is a part
of session, and session uses cookies... so when i disable cookie in
Firefox, a Rails app that was working shows
[error]
ActionController::InvalidAuthenticityToken
so is it true that for a RoR app to work, cookies are mandatory?
Update: or, to make the Rails app work again, what is the simplest way? (and if it is one server only (Apache running mod_rails), then is it easier?)
They are not mandatory, but there are some things you can't do without cookies. You can turn the authenticity tokens off as described here.
It's not mandatory to use cookies, but it is the rails default from 2.x up. Using cookies serves as a simple solution to some more difficult problems that arise when you try to store cookies in memory on multiple servers (and you get into things like sticky sessions, losing user data etc).
You can set where rails stores your session data; that is the flash and anything that's associated with the specific user. In environment.rb you can configure where you store your sessions using the config.action_controller.session_store. The options for this are: :cookie_store, :active_record_store, :p_store, :drb_store, :mem_cache_store, or :memory_store.
cookie_store is the default, if you comment the option out or remove it from environemnt.rb. It's also the most versatile. If you have multiple servers, one request for a user might come into one server, and the next request might come into a different server. In this situation, you couldn't use memory_store, as the 2nd server wouldn't know anything about the current user.
By storing session information in an encrypted cookie, there is less load on the server to store this information. The only downside is that each request to the server needs to pass the cookie (usually <1k), but it's not a noticeable difference in anything I've ever experienced.
:cookie_store, :mem_cache_store and :active_record_store are the most commonly used ones.