For one example, see this from a year ago: https://github.com/rails/rails/pull/3777#issuecomment-289375...
> If we ignore them, this means a recently created, pushed and then cloned project is not going to work at all.
Some people replace it with a new file upon deployment, some people use ENV vars, some (most) people never open-source their app, and don't mind employees seeing it...
I personally do https://github.com/hotsh/rstat.us/blob/master/config/initial...
Being generic is hard.
> some (most) people never open-source their app, and don't mind employees seeing it...
One of my concerns is that people believe it's only a risk if they ever open source their application. While most apps don't have to worry about a motivated attacker in reality, the risk isn't simply secure or unsecure.
It's more a case of 'more difficult' vs. 'much easier' to compromise. I fear many engineers don't think of securing their apps like this. I know I've only recently begun to understand this way of thinking about security and it's changed the way I code.
[1] https://news.ycombinator.com/item?id=5007530
[2] http://blog.phusion.nl/2013/01/04/securing-the-rails-session...
To a newbie like me, everything will "just work" in development. In production, I'll get a pretty explicit/precise error message.
The primary advantage I intended was that the secret is confined to one part of the infrastructure (e.g. production server) instead of many (e.g. developer workstations, github, etc).
I hate code like this that is explicitly aware of the environment. The code says what it will do in an environment, rather than the environment saying what the code should do in it.
if ENV['SECRET_TOKEN'].blank? raise 'SECRET_TOKEN environment variable is not set!' end
App::Application.config.secret_token = ENV['SECRET_TOKEN']
Even better, raise 'SECRET_TOKEN not set! Please refer to the doc in xyz'
So, the specific method for setting is in an "xyz" doc that your team keeps in a SEPARATE location from the code repo.
And, we really need a standard way to do this, or Github pulls / forks will have more friction or bad security when setting up forks.
Also, I really would rather put it in a file, not system env, as the env might be setup different on different systems, & you'd hate to have that env potentially shared in multi-user systems. Files are more reliably locked down.
In: `actionpack-3.2.13/lib/action_controller/metal/http_authentication.rb`:
raise "You must set config.secret_token in your app's config" if secret.blank?I haven't run into any problems using that method. Does anyone see a reason to prefer environment variables over it?
The envdir program (from daemontools) is useful for setting environment variables in a shell-agnostic way, e.g., run your app with:
envdir ./env python app.py
See alsoWorse. Knowing the secret token allows an attacker to trivially execute code in your application.
Don't ever let your secret token become public knowledge, and if it does, you need to change it straight away.
http://daniel.fone.net.nz/blog/2013/05/20/a-better-way-to-ma...
Unless you're grabbing that key out of "secure memory", a HSM or a TPM then its not really particularly secure.
Here's a great example of the repo file checkin fail though: http://bit.ly/10dLiDz
$ SECRET_TOKEN=abcdef SOME_OTHER_VAR=hello rails s
or pollute your .profile with a bunch of app-specific variables.
You don't need it to do it; it just makes it easier.
secret_token = File.read('secret_token_dont_check_in')
I fail to see how loading the file into the environment and then into the variable is anything but worse.The entire principle behind HTTP - what enabled it to conquer and dominate the internet, is its statelessness. Storing and trusting things in cookies is a fundamental security design flaw.
Authentication on every request requires you to store the user's authentication details on the client, which is considerably worse for security purposes than a signed or encrypted session cookie.
However, I think that relying on a single easy-to-compromise security token as a single point of failure for your app's security is terrible practice.
A secure user authentication system is usually built by having a users database that contains [user_id, nonce, password_key = pbkdf2(password, nonce)]. When logging the user in, you should store this information in a cookie: [user_id, login_timestamp, authentication_token = hmac-sha256(nonce, login_timestamp, password_key)]. Then, on every subsequent request, you would verify that the authentication_token matches what you'd expect based on the login_timestamp and user_id that the client has provided. (Substitute this for any equivalent-security scheme and crypto primitives.)
Now, if you have such a scheme in place, a secret token would provide no additional security. You really shouldn't be storing session information in cookies, but if you must, you can use a key derived from the nonce to sign the cookie, removing the need for an app-global secret. But really, don't do that, you should use a server side datastore for session information (like shopping carts, etc.).
If you do not have such a scheme in place, you app is much more vulnerable to attack. Something based on one global secret token (which by default is checked in to your source code) opens up many more attack vectors that might compromise the security of your app.
[1]: http://www.gorillatoolkit.org/pkg/sessions#NewCookieStore
App::Application.config.secret_token = ENV['COOKIE_SECRET'] || '<default secret>'
Secured environments like production get their own secret. Developer machines can use the default w/o additional overhead.