Devise loses session after deploy - ruby-on-rails

I have a rails 4 app where I am using devise for authentication and it works perfectly. My only problem is that it loses the session of a user after I deploy it on the server and the users have to sign in again.
If I just do a restart of nginx/passenger (which I am using for my app) it doesn't loses it.
When I am deploying my app I am losing it. For deploying I am also wipe out all the database automatically and my deployment script runs the seeds file which it also generates the users.
We are currently developing the app so this kind of behavior is acceptable for now, but in the
future when the app will be ready, we won't do it like this way (of course!).
So is this an issue due to the reseeding or I should check something else? I see that the encrypted password changes everytime I run the wipe out/seed action, does this have to do with the losing of user session?

You should never wipe out a database during deployment. Imagine that your app is running and you have hundreds of users. Now you make some changes in the code and do a deploy. POOF all your data and users are gone! Certainly this is not what you want.
Secondly, users getting logged out when you wipe out the database could be due one of the following reasons:
Are you seeding users with the same ID? If the user ID changes when you re-seed, it will cause users to be logged out
Are you storing sessions in the database using config.session_store :active_record_store instead of using cookies? In this case, wiping out the database will delete the sessions table and log out all users
Rails 4 uses an encrypted cookie store by default. Make you sure you're not changing your application's config.secret_token when re-deploying, in case its getting loaded from the database
Ultimately, wiping out the database is the sole reason why your users are getting logged out, and that is a bad practice. So the most important thing to fix is do not wipe data during deployments.

The reason for this behavior is the following:
Everytime some user changes his password, devise automatically signs_out him.
So, basically by reseeding the data, the password is recalculated (even though the password is the same, the new encrypted password is different from the old one). So the devise will automatically sign_out the user, because it seems like the password is changed (based on the different encrypted_password field).
I managed to bypass this behavior, by specifically setting up the encrypted_password in the seeds.rb file and bypassing the validation.

If I just do a restart of nginx/passenger (which I am using for my
app) it doesn't loses it. When I am deploying my app I am losing it.
For deploying I am also wipe out all the database automatically and my
deployment script runs the seeds file which it also generates the
users.
If you generate new users, the old ones will lose their sessions.
This is because the values of the new users will be different. For example, they might not have a remember token set, or if the session_id uses the values of user.created_at or user.token_generated_at they will be different every time you drop and recreate your database.

Related

Is it safe to increase BCrypt logrounds for a live Grails application using Spring Security without re-encoding all passwords?

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

How to track a user's session without requiring them to login with ruby on rails

I have an application that has an actual map of objects that any visitor can view as long as they have the correct access code. I don't require the user to login because I don't want to make them create an account as it is unnecessary. I want to allow the users to mark the objects on the map with a check and save the edits within the session. So if the user refreshed the page or they close the application and reopen it an hour or so later, I would like to save their marks based off their session id. But I am confused on how to set this up without requiring them to login because I am unsure how the sessions would work.
Any help would be greatly appreciated!
Sessions in Rails work the exact same way regardless if you have a proper authentication system or not.
When a first time visitor visits your application the sessions middleware creates a session identifier. This is a cryptographic hash that is kept by the server and also passed to the user in a cookie.
This lets you identify users across requests.
This session identifier is also linked to a session storage. By default this is ActionDispatch::Session::CookieStore which lets you store session data in a encrypted cookie held by the client. This is where you would normally store a user id. Since its a cookie the amount of storage space is very limited. If you want to store more data in the session you can use a different store such as Memcached, Redis or ActiveRecord.
But what you may want to consider is creating (guest) user records implicitly without the normal sign up procedure. I would just use Warden and have a bare bones user model and a cron tab that cleans out unneeded data periodically.
This gives you a database oriented application model where you can use associations and build it like a standard rails application instead of the untestable mess that results when someone goes bonkers with sessions.
I would implement Cookies (with their permission of course). You can store basic data in it, or even create a sort of ID for them so when they return you can restore their settings

Grails and Spring security: password is invalid after some time?

I'm trying to migrate old Grails app from AppFog to Linode servers. I migrated code and MYSQL database, but I couldn't log in with old credentials.
For some reason, I suspected that I forgot password so I simply deleted my user directly from the database and let Bootstrap.groovy creates a new one with known password so I managed to log in again.
Next day, when I tried to log in again, I received wrong credentials message so I looked at the database and verified that hashed password is still the same. I repeat delete user and Bootstrap procedure and noticed that password hash is different than the previous one for the same password.
Again, I managed to log in through GUI and even (via GUI) update password for other users (user from Bootstrap.groovy have admin role). I verified that all password hashes were updated in databases and I verified each account login via GUI, everything was fine.
This morning, when I tried to log into the application I was rejected again on several accounts that I verified last night.
The only thing that I noticed that is different is the format of hashed password: previously it was a sequence of chars and numbers but now it always starts with $2a$ and containing special characters.
I noticed few forums and SO post mentioning that using spring-security-gui could cause double hashing of passwords but I'm not using that plugin.
Here is the list of (relevant) plugins that I'm using:
tomcat:7.0.52.1
hibernate:3.6.10.9
database-migration:1.3.8"
spring-security-core:2.0-RC4"
I just noticed that the old version of app was using spring-security-core:1.2.7.3 and latest one is using 2.0-RC4 (I updated some out-dated plugins before migration)
UPDATE:
Unfortunatelly, problem is still active. I bootstraped user and verify that password is hashed in 'sha format'. I can log in with that user and change passwords of other users. I verified that all passwords are sha hashed in database. I can log with each user that I resetted password including bootstraped one. After one day (aproximately) I can not log again with previously used credentails on any user. I checked database and password hashes are same as before. Nothing in tomcat, mysql or syslog logs. Same application was running on AppFog for more that one year without restart and no problems were noticed. I'm not 100% sure what spring security plugin version was used at AppFog site (legacy maintenance) but, only thing that is changed is version of that plugin (if it wasnt used before). There are no background jobs that can trigger this behavior (e.g. user.save() calls) so I don't have a clue what could go wrong or what else I need to set.
Set the following two properties in your Config.groovy
grails.plugin.springsecurity.password.algorithm = "SHA-256"
grails.plugin.springsecurity.password.hash.iterations = 1
That will also allow you to log in with the old password. Spring Security 1.x uses the SHA-256 but the new Spring Security 2.x uses now bcrypt algorithms.
http://grails-plugins.github.io/grails-spring-security-core/v2/guide/newInV2.html

Rails 2.3: Session not available for first request after server restart

I'm currently upgrading a rails application from 2.1.0 to 2.3.14.
Most things are running well now, but there's a strange issue with the user sessions:
When a user has been logged in, this is saved in the session and is available even after a browser restart - as it should.
However: When I restart my local server and load a page that requires authentication, the following happens:
Rails creates a new session row in the database with exactly the same session_id as before.
Inside the application the "old" session is not available, old session data is not available.
If I simply reload the page (F5) afterwards, the correct session including the old data is loaded fine.
The application uses ActionController::Base.session_store = :active_record_store and multiple databases (one per subdomain, wasn't my decision). The correct database is chosen as before_filter and rails saves sessions in these databases.
My guess is that after a server restart something is not yet set correctly and the sessions are searched in a wrong database and kept for the first request (but it's saved in the correct database after it was set via ActiveRecord::Base.establish_connection).
If my guess is correct, loading the correct session after establishing the connection should solve this.
Is there a way to either completely reload the session from database or tell Rails to use a custom database for all sessions?
Thanks in advance!

How do I prevent Rails users from accidentally authenticating as the wrong user?

Specifically, I have written a Rails app in which I'm using the default (in Rails 2.3.5) CookieStore session store and I've spotted an odd problem in development.
Myself and a few others had been using the site for a few weeks and we each had a login based on a username and password (each user registered themselves and I stored the (salted and hashed) data in the database). I was storing the user ID in the Rails session object (and, therefore, in the cookie that is passed back and forth between browser and server).
One important point here: since this is an intranet site, I set the cookies to stay alive for up to 2 weeks to avoid users having to log in all the time.
Today I reset the database, wiping all user records (and all other data, intentionally). A few users started registering themselves again and then one user found that the first time they went to the site since the wipe they were automatically logged-in as a different user!
I think I can see why this happened: the user ID passed from that user's browser to the server now matched a different user-record in my database. My initial thought was "oh dear, I wasn't expecting that!" but the more I thought about it the more I realised this was probably expected behaviour.
I realise I can change my Rails app to user ActiveRecordStore but before I did that I wanted to make sure I understand what's going on here. Specifically, does the combination of using CookieStore sessions and having the sessions stay alive for some time really create such a gaping security hole? Or am I missing something? Should the session_id be providing a little more security here?
The big security hole in this setup isn't the cookie length, it's setting the user_id in a cookie. This means that anyone who logs into your site can log in as anyone else just by changing that cookie! A hacker would just sequentially walk through user_id's, logging in and seeing if there's anything they want to steal or abuse.
If you want to roll your own authentication, try this instead: add a "token" string field to your user table. When somebody logs in, set this token to a random set of numbers and letters, and pass that as the cookie back to the user. The token should be at least 32 characaters, alphanumeric, upper and lower case.
Now when a user goes to a page, their account is looked up by that hash instead of their user_id. The value is that the hash is much harder to guess, and will never be repeated. Your user_id's were actually repeated when you reset the database, causing people to be logged in as each other.
UPDATE
#shingara is right that the cookie store does handle the security part already, my mistake. The user_id mixup is therefore a one-time occurrence because you reset the database. This is not a problem you'll face in a production environment, unless you reset the database again. If resetting is ever a possibility, then still do the token creation as I recommended. Otherwise, you're fine.
The simplest solution to the problem you had here would be to have changed the cookie name when you reset the database. The cookie name should be in config/initializers/session_store.rb
ActionController::Base.session = {
:key => '_your_app_session_v2',
You could also change the secret, but that may generate errors for your users if they request the site with an old cookie.
You case arrived only if you have 2 differents user with the same user_id. So it's not possible if you define the user_id like unique.
Another case, you can add in session, an hash with an unique key by user. when you check the session you get the user_id and check if the user_token is same . If not, the user is not authorized.
Thankyou for all the responses. They all answered my question in a way: yes, my setup (and my not setting a new session key after wiping the users) creates a security hole.
Lots of Rails tutorials advocate this setup without mentioning the fact that all you need is to monkey with your cookie to be fully authenticated as another user.
So, to summarise, I asked the question because I couldn't find anything discussing the danger of CookieStore session + long cookie lifetimes, and I found that surprising so thought I might be missing something obvious.
I had a similar issue and resolved it using a code snippet similar to
this comment by mdesantis on managing Rails secret token

Resources