Improve upgrade guide section on cookies rotator (#44967)

* Improve upgrade guide section on cookies rotator

The Rails upgrade guide, in the section about upgrading from Rails 6.1 to Rails 7.0, contains some example code defining a cookie rotator for encrypted cookies, as Rails 7 changed the default digest for the key generator from `SHA1` to `SHA256`. The problem is that the provided example code only rotates encrypted cookies, and not signed ones. Rotating signed cookies is also usually necessary for the same reason, and failure to do so results in old cookies not being read. For example, when using the popular Rails authentication framework [Devise](https://github.com/heartcombo/devise) with the `rememberable` strategy, the "remember me" token is saved as a signed cookie, and without defining a rotator all users would be logged out following an upgrade to Rails 7.

This change improves the example code in the documentation by also rotating signed cookies. Note that providing an example is important, because rotating the signed cookies involves some technicality that is not obvious to users who are not comfortable with reading the [relevant Rails internal code](649516ce0f/actionpack/lib/action_dispatch/middleware/cookies.rb (L615)) (a different salt is used for signed cookies, and the `key_len` argument is omitted when generating the secret).

The improved example code should hopefully save some mistakes for users following the upgrade guide.

* Apply suggestions from code review

Better naming for the signed cookie salt variable

Co-authored-by: Vipul A M <vipul@hey.com>

* Apply suggestions from code review

Better naming also for the authenticated encrypted cookie salt variable

Co-authored-by: Vipul A M <vipul@hey.com>

Co-authored-by: Vipul A M <vipul@hey.com>
This commit is contained in:
Luca Ongaro 2022-04-27 15:20:59 +02:00 committed by GitHub
parent 649516ce0f
commit f8974286da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -374,22 +374,27 @@ encrypted cookies.
In order to be able to read messages using the old digest class it is necessary In order to be able to read messages using the old digest class it is necessary
to register a rotator. to register a rotator.
The following is an example for rotator for the encrypted cookies. The following is an example for rotator for the encrypted and the signed cookies.
```ruby ```ruby
# config/initializers/cookie_rotator.rb # config/initializers/cookie_rotator.rb
Rails.application.config.after_initialize do Rails.application.config.after_initialize do
Rails.application.config.action_dispatch.cookies_rotations.tap do |cookies| Rails.application.config.action_dispatch.cookies_rotations.tap do |cookies|
salt = Rails.application.config.action_dispatch.authenticated_encrypted_cookie_salt authenticated_encrypted_cookie_salt = Rails.application.config.action_dispatch.authenticated_encrypted_cookie_salt
signed_cookie_salt = Rails.application.config.action_dispatch.signed_cookie_salt
secret_key_base = Rails.application.secret_key_base secret_key_base = Rails.application.secret_key_base
key_generator = ActiveSupport::KeyGenerator.new( key_generator = ActiveSupport::KeyGenerator.new(
secret_key_base, iterations: 1000, hash_digest_class: OpenSSL::Digest::SHA1 secret_key_base, iterations: 1000, hash_digest_class: OpenSSL::Digest::SHA1
) )
key_len = ActiveSupport::MessageEncryptor.key_len key_len = ActiveSupport::MessageEncryptor.key_len
secret = key_generator.generate_key(salt, key_len)
cookies.rotate :encrypted, secret old_encrypted_secret = key_generator.generate_key(authenticated_encrypted_cookie_salt, key_len)
old_signed_secret = key_generator.generate_key(signed_cookie_salt)
cookies.rotate :encrypted, old_encrypted_secret
cookies.rotate :signed, old_signed_secret
end end
end end
``` ```