The Play Framework for Scala has support for signed session cookies. In the application configuration file is an "application secret" that is set as a secure random number when the application source code is initialized. This secret is shared between multiple copies of the application running in a web server farm so that all cookie signatures can be checked on any server.
When a session is created in Play, the session is automatically signed using the application secret and HMAC-SHA1.
I am concerned that the same application secret is used for the life of the application. Is this concern valid?
I was trying to come up with a better way to sign the cookies, but I know the adage against inventing your own cryptographic techniques.
Is there some accepted way to have all of the servers share a changing secret?
I thought of the following (note that all session cookies are in-memory only and expire when the browser is closed):
- Embed the signature date (UTC) in each cookie.
- The signing key is randomly generated by the first signing of the day (after midnight) and stored in the database for all servers to share.
- When a server needs to sign a cookie, it checks its own signing key and the date it was generated and compares that date to the current date.
- If the signing date is the same as the current date, the key is used to sign the cookie.
- If the signing date is older than the current date, the server checks the database for a new signing key with the current date.
- If there exists a key with the current date in the database, it is used for signing the new cookie. Old signing keys are retained (for some number of days) to verify older cookies.
- If there is no key for the current date, a new one is generated (how do I handle multiple servers doing this at the same time in a NoSQL database?).
As an alternative algorithm, I can generate a new secret each day using HMAC(application secret, current date). With this, I do not need to store the daily secret keys in the database, since all servers can generate the same daily key sequence. I'm not sure if this is any more (or less) secure than storing the daily key in the database. I do need to protect the application secret, but no more so than I need to protect the database. It is recommended that the application secret not be stored in source control, but loaded from an environment variable set on each production server.