I am new to Rails 4, and do not understand the use of secret_key_base under config/secrets.yml in Rails 4. Can you please explain this concept?

Also, when I am working in the production environment, I am prompted to set the secret_key with devise.rb, config.secret_key, and secret_key_base. However, I can generate a new secret using the rake secret command.

What is the difference between development and production environments?

How is it matching the newly generated secret_key when I add it with secret_key_base every time I generate?

How is it securing the application with other servers?


Solution 1:

The secret_token.rb file's content includes a long randomized string which is used to verify the integrity of signed cookies (such as user sessions when people are signed into your web app).

Documentation says:

Use your existing secret_key_base from the secret_token.rb initializer to set the SECRET_KEY_BASE environment variable for whichever users run the Rails app in production mode. Alternately, you can simply copy the existing secret_key_base from the secret_token.rb initializer to secrets.yml under the production section, replacing <%= ENV["SECRET_KEY_BASE"] %>.

Since it is important file, and you can't put it to .gitignore, it is treated to be a good practice to use env variable to store secret_key_base value:

create .env or .powenv file and store it as:

export SECRET_TOKEN="9489b3eee4eccf317ed77407553e8adc97baca7c74dc7ee33cd93e4c8b69477eea66eaedeb18af0be2679887c7c69c0a28c0fded0a71ea472a8c4laalal19cb"

And then in config/initializers/secret_token.rb

YourAppName::Application.config.secret_key_base = if Rails.env.development? or Rails.env.test? # generate simple key for test and development environments
  ('a' * 30) # should be at least 30 chars long
else
  ENV['SECRET_TOKEN']
end

This article is (a bit old and) long but really full of useful info on the topic.


UPDATE 04.05.15

Starting from Rails 4.2 there is no longer secret_token.rb file. By new convention there is a config/secrets.yml file aimed to store application's secrets.

Have a read on how to upgrade an existing app to 4.2.x according to innovations.


Technically the purpose of secrect_key_base is to be the secret input for the application’s key_generator method (check Rails.application.key_generator).

The application’s key_generator, and thus secret_key_base, are used by three core features within the Rails framework:

  • Deriving keys for encrypted cookies which are accessible via cookies.encrypted.
  • Deriving the key for HMAC signed cookies which are accessible via cookies.signed.
  • Deriving keys for all of the application’s named message_verifier instances.

Check out more on each of the three in the article by @michaeljcoyne.

Solution 2:

secret_key_base is used to encrypt and sign session

in order to safely send session back and forth in cookies


In Rails 4,

  1. if your app is called Hello, and
  2. you set session['a'] = 'b',

your cookie will look something like this:

_Hello_session=BAh7B0kiD3%3D%3D--dc40a55cd52fe32bb3b84ae0608956dfb5824689

which translates into:

_Hello_session=<encrypted a=b>--<digital signature>

Cookies are set by server and kept client side, with browser resending set cookies to the server every time we request a page.

To prevent evil people from understanding a=b string, it's encrypted.
To prevent evil people from tampering cookies, digital signature is used.

In both cases secret_key_base value is used (to encrypt/decrypt a=b and to validate digital signature).