Rails how to use an in Memory SessionStore - ruby-on-rails

I'm looking for a way to use an in memory based session store in a Ruby on Rails application. The session contains a masterkey which can only be decrypted when the users logs in. This key should be available during the entire session.
Due to the nature of this key, the content of the session should not be stored anywhere locally. Also I don't want to transfer the content to any external application, such as memcached.
Thus is it possible to just use an in memory based session store similar to PHP or Java SE?

Rails 5
From version 5, Rails no longer creates a config/initializers/session_store.rb file at install.
In rails 5, the default session store is setup internally (to cookie store), and no longer through an application initializer, as was the case up to Rails 4.
cf. https://github.com/rails/rails/issues/25181
In a pure Rails 5 app (= non-migrated), to change your session store, e.g. from :cookie_store to :cache_store, you will have to create yourself the config/initializers/session_store.rb file, and then add the relevant instruction:
# Be sure to restart your server when you modify this file.
Rails.application.config.session_store :cache_store, key: '_your_app_session'
Beware that you will need to change the key from '_your_app_session' to match your application name (if for ex your app is named calculator then should be '_calculator_session')...

You can use a CacheStore to store session data in-memory.
# /config/initializers/session_store.rb
AppName::Application.config.session_store :cache_store
Or you can write your own SessionStore class:
http://guides.rubyonrails.org/configuring.html#rails-general-configuration

You can use a MemoryStore, but it's a really bad practice as it is not shared between machines, so your application will not be scalable.
From a security standpoint there's no real reason you shouldn't transfer this key to an external memcached or redis.
You should secure your production infrastructure as a whole, encrypt any data exchange between your servers, or put them in a trusted network, make good use of firewalls and follow best practices. Your cache servers should be as secure as your app servers, or databases, no excuses.

Related

rails: What are the consequences of a leaked secret_key_base

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.

Where to store system passwords in the Rails directory tree?

I have a number of 'system' passwords in my Rails app, such as database passwords and separate HTTP authentication passwords for an XML feed.
My trouble is knowing exactly how to store these passwords in my directory so they are as safe as they can be. What are your recommendations specifically for Rails 3?
encrypted in a database?
in environment config?
I've used both in the past. The reality is that HTTP passwords are more like an API key. The provider of the service has the responsibility that you can't do anything 'evil' with access. In general, recommend against putting anything in source control you don't want to be public. In the past, I've had to deploy separate key files outside of my app. If you're doing really secure stuff (a la credit cards), then you can do that. And just create a user on the server that has access to the keyfiles. Then you're actually using access to the Unix box as your security model, not the password to your keyfiles.
Just make sure to store your config-files in the config-folder (or at least outside the public-folder ;). Besides this you should secure the access to your rails-app-user-account from outside (force ssh-pubkey authentication).
Another security-flaw is checked-in config-files with sensible password information (e.g. database-access). I alway add config/database.yml to .gitignore and check-in a default config/database.sample.yml as a template for other developers. The "real" config/database.yml is created and configured manually with environment-specific configuration-values.

In a Sinatra App on Heroku, Session Is Not Shared Across Dynos

Which makes sense. But what are some preferred work arounds for this issue?
In my comment, I suggested using rack cookie based sessions, but looking into it, the Sinatra sessions are Rack cookie sessions anyway.
Looking further, I found this in the Sinatra docs:
To improve security, the session data in the cookie is signed with a session secret. A random secret is generate for you by Sinatra. However, since this secret will change with every start of your application, you might want to set the secret yourself, so all your application instances share it:
set :session_secret, 'super secret'
So it seems each Heroku dyno is generating a different key, and so can't read each others session cookies, and you need to specify a key so each dyno uses the same one.
Rather than add a secret key to your source code, you're probably better setting an environment variable:
$ heroku config:add SESSION_KEY=a_longish_secret_key
Then in your sinatra app:
enable :sessions
set :session_secret, ENV['SESSION_KEY']
You can also use a memcached session for performance or security. Have not tried it but looked easy. 5MB free on heroku.
# In your app.rb file just add following -
enable :sessions
set :session_secret, "some_random_value"

Rails sessions current practices

Anyone have any "best practices" tips for Rails and sessions? The default session type for Rails 3 is still CookieStore, right? I used SqlSessionStore for a while and it worked well, but I may move away from that in favor of CookieStore.
Is it still not a good idea to use CookieStore for sensitive info, even with salted info or is that better stored in the DB?
Use the database for sessions instead of the cookie-based default, which shouldn't be used to store highly confidential information
Create the session table with
rake db:sessions:create
Run the migration
rake db:migrate
Make sure you also tell rails to use ActiveRecord to manage your sessions too.
Rails 3
config/initializers/session_store.rb:
Rails.application.config.session_store :active_record_store
Rails 2
config/environment.rb:
config.action_controller.session_store = :active_record_store
Cookies are encrypted by default in Rails 4
In Rails 4, CookieStore cookies are encrypted and signed by default:
If you only have secret_token set, your cookies will be signed, but not
encrypted. This means a user cannot alter their user_id without knowing your
app's secret key, but can easily read their user_id. This was the default
for Rails 3 apps.
If you have secret_key_base set, your cookies will be encrypted. This goes a
step further than signed cookies in that encrypted cookies cannot be altered
or read by users. This is the default starting in Rails 4.
If you have both secret_token and secret_key_base set, your cookies will
be encrypted, and signed cookies generated by Rails 3 will be transparently
read and encrypted to provide a smooth upgrade path.
Active Record Session Store is Deprecated in Rails 4
This answer is now out-of-date with regard to Rails 4. The Active Record
Session Store has been deprecated and removed from Rails, so the following
generators will no longer work:
rake db:sessions:create
rails generate session_migration
This was pointed out in this answer. The reason that the Active Record
Session Store was deprecated is because the reads/writes to the database don't
scale well when you have a large number of users accessing your application, as
stated in this blog post:
...one major issue with the Active Record session store is that it is not
scalable. It puts an unnecessary load on your database. Once your application
receives a large amount of traffic, the sessions database table is
continuously bombarded with read/write operations.
As of Rails 4, the Active Record session store has be removed from the core
framework and is now deprecated.
If you still want to use the Active Record Session Store, it's still available
as a gem.
Current Rails Session Best Practices
For more current best practices for Ruby on Rails sessions, I advise that you
check out the lastest versions of the Ruby on Rails Security Guide.
I don't believe anything has changed in how anyone on any platform should handle cookie based sessions. Be skeptical of anything that passes beyond the server's control (cookies, form posts, etc.) Thats a general principle of web development.
As far the encryption, I don't know if anything has changed on that front.
Something to be mindful of with a cookie store is the limit to the amount of data, and the gotcha that this data will be sent on the wire in every request, where as a database store only transfers the id and the data lives on the server.
FWIW, rails 3.1 suggests running
rails generate session_migration
However this generates the exact same migration as
rake db:sessions:create
The Rails defaults seem pretty good to me- The CookieStore is fast and should cover the majority of use cases. Sure you're limited to 4kb and your data will be visible to the user, but the Rails way is to only use session for things like integer IDs and basic string values- If you're trying to store objects or highly confidential information in session you're probably doing it wrong.

are cookies mandatory for Ruby on Rails app?

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.

Resources