According to the docs Rails, (currently: version 6) supports two kinds of cookies: session cookies and persistent cookies; the latter having a defined expiry date at some time in the future (and might persist during a clientside reboot).
Sadly, the latter ones do not work as expected. Instead, they are silently changed to session cookies at the next encryption key rotation.
I might miss some point, but from studying the code, I get the impression that the whole thing, as promoted here, can never have worked. Or am I doing it wrong?
Rails has a concept of a “rotation”. This means, one can change security parameters, and then do a phased upgrade, where the old and the new parameters are both valid for some time, and all encountered secrets will be transparently re-encrypted with the new parameters.
After such a rotation the cookies which are returned in from the clients will also need to be re-encrypted and then stored back onto the client. But the client does not return the expiration date of the cookie, so this is ‘nil’ when recreating the cookie, and consequentially the cookie becomes a session cookie. To solve this, one would need to store the expiration date explicitely within the cookie payload.
Addendum: I did some further research and found that we do already have the expiration date stored within the cookie payload!
This is done in
ActiveSupport::Messages::Metadata. But that data is encapsulated there and only used to verify the validity of the cookie, it is not made accessible to the CookieJar. Grabbing it from there, moving it thru the
MessageEncryptor and then onwards to the
EncryptedRotatingKeyCookieJar and to the
SerializedCookieJars (where we would need it) appears to be not something that is supposed to be done.
(It appears to work, nevertheless.)
What appears strange to me: the Rotating Cookies were introduced somewhere at Rel. 5.2, and the Messages Metadata also appeared about 5.2 - but somehow it was not supposed to have these two connected.
Another word - why I care about this:
The secret key base is the core security anchor for the whole application. And it seems not popular to change it regularly. I don’t understand that: we have learned long ago that we must change our personal passwords every three months. We learn now that we should update certificates every three months. Security guys know that risks grow exponentially over time.
But with Rails, only a few years ago somebody had the great idea that it is not so good to store the secret key base on github. And then that was remedied. Well, somehow. It’s actually hard to believe.
The only one who seems to ever have cared about it is this guy here. And that works, and it can be automated.
Any ideas why this is not popular? I would rather think it should be the default to change the thing every three months, unless really serious reasons prohibit that.