63

The documentation of ActionDispatch::Cookies gives nearly identical descriptions for both signed cookies and encrypted cookies. It appears that both use secrets.secret_key_base to prevent client-side tampering. http://api.rubyonrails.org/classes/ActionDispatch/Cookies.html

Signed Cookies

Sets a signed cookie, which prevents users from tampering with its value. The cookie is signed by your app's secrets.secret_key_base value. It can be read using the signed method cookies.signed[:name]

cookies.signed[:user_id] = current_user.id

Encrypted cookies

Sets an encrypted cookie value before sending it to the client which prevent users from reading and tampering with its value. The cookie is signed by your app's secrets.secret_key_base value. It can be read using the encrypted method cookies.encrypted[:name]

cookies.encrypted[:discount] = 45

My question is: What is the difference between the two?

When would you want to use one over the other?

Sean Huber
  • 3,945
  • 2
  • 26
  • 31

2 Answers2

95

It's subtle, but the answer is in the documentation you provided. Signed cookies only guard against tampering, while encrypted cookies guard against reading and tampering.

More specifically, signed cookies call ActiveSupport::MessageVerifier to append a digest (generated using secret_key_base) to the cookie. If the value of the cookie is modified, the digest will no longer match, and without knowing the value of secret_key_base, the cookie cannot be signed. The value of the cookie is merely base64 encoded, however, and can be read by anyone.

Encrypted cookies called ActiveSupport::MessageEncryptor to actually encrypt the value of the cookie before generating the digest. Similar to signed cookies, if the value of cookie is modified the digest will no longer match, but additionally the value of the cookie cannot be decrypted without the secret_key_base.

As to when you'd use encrypted versus signed cookies, it comes down to the sensitivity of the information you're storing in the cookie. If all you want to protect against is someone modifying the cookie, then sign it - but if you also need to keep the data secret, encrypt it.

Brian
  • 5,300
  • 2
  • 26
  • 32
  • Excellent answer! Thank you for elaborating. – Sean Huber Jan 04 '17 at 20:48
  • 2
    @7urkm3n, I've never benchmarked the two against each other, but I suspect encrypted cookies would be slower simply because more work is involved. That being said, I imagine any performance difference would be negligible unless you're dealing with millions of cookies. – Brian Jan 16 '18 at 14:12
  • 1
    Would it be good practice to encrypt the cookie values by default? Since the cookies would supposedly only be understandable by the server code – CyberMew Jun 07 '18 at 08:25
  • 1
    @CyberMew, Rails has defaulted to encrypted session cookies since version 4, so it's probably best to do so for your own cookies. – Brian Jun 07 '18 at 15:19
  • @Brian, is there any offcial documentation about this? I wasn't able to find this statement on any official page. – AlexS Feb 24 '21 at 13:39
  • @AlexS As far as I remember, this wasn't clearly documented - but the great thing about open source is that you can always read the code! :) – Brian Feb 25 '21 at 15:33
  • So it's redundant to use "cookies.signes.encrypted[:key] = value"? "cookies.encrypted[:key] = value" would lead to the same result (non modifiable and non readable cookie) right? – ShadowCrafter_01 Oct 06 '22 at 15:51
0

Signed Cookies

Properties: Can be read by the client, server prevents tampering of the value.

Usage: read-only value for frontend (makes little sense with HttpOnly)

Typically just like an encrypted cookie, but because of design shortcomings, the client (browser) also need to access its value.

I can't think of a proper example... perhaps storing user data without a server-side storage, while guaranteeing its validity? (not very efficient though)

Encrypted cookies

Properties: A secret the client get, cannot read/write and will be returned to the server.

Usage: overcome stateless part of http, e.g. sessions (makes little sense without HttpOnly)

Summary

I'd say using signed cookies is always a poor architectural decision. But under extreme constrains (no server-side storage, no javascript in the browser) could be the only solution left.

estani
  • 24,254
  • 2
  • 93
  • 76