Live data from Hacker News

A Better Way to Manage the Rails Secret Token

daniel.fone.net.nz

51–60 of 60 posts

Re: A Better Way to Manage the Rails Secret Token

#51

We've had discussions about this several times, and haven't come up with something that's satisfactory as a generic replacement, other than "configuration could probably be improved." 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 repla…

See also comments on HN[1] about an "old" post[2] from Hongli Lai (Phusion) about this topic.

[1] https://news.ycombinator.com/item?id=5007530

[2] http://blog.phusion.nl/2013/01/04/securing-the-rails-session...

Re: A Better Way to Manage the Rails Secret Token

#52
post #50

Earlier quoted context omitted.

Have you considered generating a key at first startup and storing it in a database? Or would that introduce too much unnecessary overhead while introducing an attack vector through the database?

The extra overhead could be kept pretty small. After being retrieved once, it can be cached in the memory of a server process. So, there's one short SQL query at process startup (or perhaps first request, depending on how you do it), and negligible overhead after that.

This is what I do, works great.

Most of my application secrets/configuration/keys/tokens are stored in the database.

The only one that's not is the information about how to connect to the database. That's stored in the DATABASE_URL environment variable and it's stored on each machine. envdir is used to start the apps, reading that environment data.

Re: A Better Way to Manage the Rails Secret Token

#53
The way, we've solved this is to default to a hard-coded secret if the environment doesn't have it.

    App::Application.config.secret_token = ENV['COOKIE_SECRET'] || ''
Secured environments like production get their own secret. Developer machines can use the default w/o additional overhead.

Re: A Better Way to Manage the Rails Secret Token

#54
post #6

> if Rails.env.development? or Rails.env.test? 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.

Something more like the following is probably a better solution: if ENV['SECRET_TOKEN'].blank? raise 'SECRET_TOKEN environment variable is not set!' end App::Application.config.secret_token = ENV['SECRET_TOKEN']

Rails already raises an exception for you if the secret is blank.

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?

Re: A Better Way to Manage the Rails Secret Token

#55

Earlier quoted context omitted.

Rails' default session is cookie store, highly recommended is DB. It's a config issue that depends on your app's particular DB setup, so default isn't DB. But in session_store.rb you'll see this comment recommending against the default: # 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 "rails generat…

also, in config/initializers/secret_token.rb: # Your secret key for verifying the integrity of signed cookies. Does this mean that if you use redis/db-backed sessions you can safely ignore this secret_token parameter completely or even delete this initializer? UPDATE: I just tried to remove it from our environment, and everything seems fine. Unless I'm missing something out, I'd say that's a far better and easier sol…

Since it's not only used for session cookies, I'd keep it around, on the off chance I ever wanted a signed cookie, like:

  cookies.signed['some-id'] = model.id
Rails will use the secret here too.

Re: A Better Way to Manage the Rails Secret Token

#56

Earlier quoted context omitted.

also, in config/initializers/secret_token.rb: # Your secret key for verifying the integrity of signed cookies. Does this mean that if you use redis/db-backed sessions you can safely ignore this secret_token parameter completely or even delete this initializer? UPDATE: I just tried to remove it from our environment, and everything seems fine. Unless I'm missing something out, I'd say that's a far better and easier sol…

Since it's not only used for session cookies, I'd keep it around, on the off chance I ever wanted a signed cookie, like: cookies.signed['some-id'] = model.id Rails will use the secret here too.

just curious: when would you need a signed cookie though? i.e. What need does it fulfil that neither the session store nor your database do?

Re: A Better Way to Manage the Rails Secret Token

#57

Earlier quoted context omitted.

Since it's not only used for session cookies, I'd keep it around, on the off chance I ever wanted a signed cookie, like: cookies.signed['some-id'] = model.id Rails will use the secret here too.

just curious: when would you need a signed cookie though? i.e. What need does it fulfil that neither the session store nor your database do?

I dunno, good question. Maybe something like this: there's some cases where I'll prefer cookies to session data, esp if it's non-volatile data that I can take or leave, like convenience values for the user on the js side, "last selected item" or the like.

I don't necessarily want that data in my session, or as a user attribute that I have to migrate the DB for. If it's a pkid or something that isn't necessarily sensitive, but I also don't want it to be too easy to get at, I might use a signed cookie.

Now, I've never actually done this... ;p

Re: A Better Way to Manage the Rails Secret Token

#58
post #46
post #45

Earlier quoted context omitted.

I'm not sure you understand what's going on, which is probably why you've been downvoted. The secret token ensures that the server does not need to trust the client--that's what signing or encrypting session cookies does. 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.

I wrote this comment with the assumption that we all understand the security implications of what's going on, which is why I probably did a poor job of making my point. 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_…

That's a completely valid route, for sure, but if your app's owned, your database is owned and this is going to be blown as wide open as a secret token.

Re: A Better Way to Manage the Rails Secret Token

#59
post #18

For Python website projects, I enforce the creation of a _secrets.py file in the config folder that is ignored by git and contains all sensitive constants like database information and tokens. Then, in the _base.py settings file (what all other settings files inherit from), I make sure to `from _secrets import *`. I'm not a fan of setting tokens by environment because it gets a little too unwieldy to make sure bash/z…

For me the main reason is consistency. I can write apps in Python, Ruby, node, etc. and configure them all the same way. 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 also http://12factor.net/config

Another good point. Thanks for the link, too!

Re: A Better Way to Manage the Rails Secret Token

#60
post #39

Earlier quoted context omitted.

Couldn't you just read the file directly? e.g. 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 original issue is people checking their secret token files into their VCS repository and publishing that. Getting the secret token from the ENV means it probably won't be checked into the repo.

It's still a file (how do you think it gets into the environment?). Whether it's a ruby file or a .env file or a yaml file, it's still equally at risk of being checked in.
Post reply on HN