Read more

Rails: Have different session secrets for all environments

Dominik Schöler
June 14, 2013Software engineer at makandra GmbH

This is no longer relevant in modern Railses, which uses the secret_key_base from secrets.yml, which will always differ per deployment anyways.

The Rails secret_token must be unique for each application and any instance of it. If not, someone could exploit this by creating a user with ID = 1 (e.g. on staging), sign in and then use that cookie to authenticate on another site (e.g. on production, where the user with ID = 1 probably is the admin).

Illustration money motivation

Opscomplete powered by makandra brand

Save money by migrating from AWS to our fully managed hosting in Germany.

  • Trusted by over 100 customers
  • Ready to use with Ruby, Node.js, PHP
  • Proactive management by operations experts
Read more Show archive.org snapshot

Here is a one-for-all solution that does not affect current production users, leaving the production token unchanged: prefix the existing secret_token with #{Rails.env unless Rails.env.production?}.

Note: There may be tokens in single quotes that include backslashes, double quotes etc. You should not change this to double quotes because Ruby would interpret "escaped" characters with a backslash in front of them etc. In this case, affix the token with a separate string instead: ...token = 'current_token\nfoo@#$' + "#{Rails.env unless Rails.env.production?}".

Rails 3

In config/initializers/secret_token.rb:

MyApp::Application.config.secret_token = "#{Rails.env unless Rails.env.production?}long_maximally_random_string<-.->(*^-^*)etc"

Rails 2

In config/initializers/session_store.rb (for the Rails session cookie):

ActionController::Base.session = {
  :key         => '_example_session',
  :secret      => "#{Rails.env unless Rails.env.production?}long_maximally_random_string<-.->(*^-^*)etc"
}

And in config/initializers/cookie_verification_secret.rb (for signed cookies):

ActionController::Base.cookie_verifier_secret = "#{Rails.env unless Rails.env.production?}long_maximally_random_string<-.->(*^-^*)etc"

If the session secret is set inside the Initializer block in config/environment.rb, calling Rails.env will break. Use RAILS_ENV unless RAILS_ENV == 'production' instead.

Posted by Dominik Schöler to makandra dev (2013-06-14 12:23)