Session: Secure session secrets?

Created on 13 Nov 2017  路  4Comments  路  Source: expressjs/session

In the options to set up the session there's a secret key:

app.use(session({
  secret: 'keyboard cat',
  ...
});

I don't completely understand what the secret is or why it's needed but it seems that hiding its value from everyone is important for security.

How can I securely generate and use random secrets with this middleware?

And is there a way to change (rotate) the secret every-so-often?

question

Most helpful comment

@theonlygusti I would not recommend keeping the secret internal, by which I鈥檓 assuming you mean in memory. This would make your application stateful, which is problematic if:

  • Your node process crashes, since you鈥檒l lose your session secrets.
  • You run Node in a cluster. This is almost always the case because Node is single threaded, so you need clustering to make use of more than a single CPU core.
  • You scale up to multiple servers, in which case you have the same problem as with the clusters above.

You could theoretically store your secrets in a database or key/value store and do a lookup on each request. One option for doing this would be to wrap the session middleware in a custom middleware which performs the secret lookup and the invokes the session middleware with the retrieved secret. Something like this:

app.use(async (req, res, next) => {
  // retrieve secrets from store
  const sessionSecrets = await Store.getSessionSecrets();

  session({
    secret: sessionSecrets,
    // ...other options
  })(req, res, next);
})

But personally I would go with environment variables and something like PM2鈥檚 reload command for 0-second-downtime reloads.

Hope this helps! Also, all this stuff might already be familiar to you. I don鈥檛 mean to sound condescending in any way 馃檪

All 4 comments

The easiest way would be to supply it via a node environment variable. So instead of just running node server.js, you run SESSION_SECRET=mylittlesecret node server.js.

You can access environment variables in you application like this:

app.use(session({
  secret: process.env.SESSION_SECRET,
  ...
});

You might want to check whether this secret exists because if it doesn鈥檛 this will leave your application vulnerable.

As for rotating, the easiest way to do this is manually or if you鈥檙e running something like Heroku you can often do it via command line tools.

Please note that once you rotate your secret, all active sessions will become invalid. Basically, all your users will be logged out.

More info about environment variables can be found here: https://www.twilio.com/blog/2017/08/working-with-environment-variables-in-node-js.html

@mattijsbliek rotating with an environment variable would require the app to be restarted.

I think that keeping the secret internal (i.e. not an environment variable) is more secure and also easier to manage. Keep in mind I want to automate secret creation, this can be done from within node so what's the point of the environment variable?

As for rotating and invalidating previous sessions, I know that session now allows you to set the secret to an array of valid secrets.

@theonlygusti I would not recommend keeping the secret internal, by which I鈥檓 assuming you mean in memory. This would make your application stateful, which is problematic if:

  • Your node process crashes, since you鈥檒l lose your session secrets.
  • You run Node in a cluster. This is almost always the case because Node is single threaded, so you need clustering to make use of more than a single CPU core.
  • You scale up to multiple servers, in which case you have the same problem as with the clusters above.

You could theoretically store your secrets in a database or key/value store and do a lookup on each request. One option for doing this would be to wrap the session middleware in a custom middleware which performs the secret lookup and the invokes the session middleware with the retrieved secret. Something like this:

app.use(async (req, res, next) => {
  // retrieve secrets from store
  const sessionSecrets = await Store.getSessionSecrets();

  session({
    secret: sessionSecrets,
    // ...other options
  })(req, res, next);
})

But personally I would go with environment variables and something like PM2鈥檚 reload command for 0-second-downtime reloads.

Hope this helps! Also, all this stuff might already be familiar to you. I don鈥檛 mean to sound condescending in any way 馃檪

Thanks @mattijsbliek. You Helped me a lot!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aheyer picture aheyer  路  15Comments

azfar picture azfar  路  14Comments

Jpunt picture Jpunt  路  17Comments

scaryguy picture scaryguy  路  16Comments

renehauck picture renehauck  路  16Comments