Skip to content

Commit

Permalink
Use authenticated cookie options to disable embedding of the expirati…
Browse files Browse the repository at this point in the history
…on in the cookies

We were generating the cookie value with the expiry information embedded what
makes the value impossible to be read by a Rails 5.1 application.

This option is only useful if you need to share your cookies between
a Rails 5.1 and a Rails 5.2 application, or if you are still validating
the deploy and wants to eventually rollback.
  • Loading branch information
rafaelfranca committed Mar 6, 2018
1 parent 96e4ac6 commit b25fcbc
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 3 deletions.
10 changes: 7 additions & 3 deletions actionpack/lib/action_dispatch/middleware/cookies.rb
Original file line number Diff line number Diff line change
Expand Up @@ -490,10 +490,14 @@ def request; @parent_jar.request; end

private
def expiry_options(options)
if options[:expires].respond_to?(:from_now)
{ expires_in: options[:expires] }
if request.use_authenticated_cookie_encryption
if options[:expires].respond_to?(:from_now)
{ expires_in: options[:expires] }
else
{ expires_at: options[:expires] }
end
else
{ expires_at: options[:expires] }
{}
end
end

Expand Down
24 changes: 24 additions & 0 deletions actionpack/test/dispatch/cookies_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,18 @@ def test_signed_cookie_with_expires_set_relatively
assert_nil cookies.signed[:user_name]
end

def test_signed_cookie_does_not_embed_expiration_if_config_is_set_to_false
@request.env['action_dispatch.use_authenticated_cookie_encryption'] = false

cookies.signed[:user_name] = { value: "assain", expires: 2.hours }

travel 1.hour
assert_equal "assain", cookies.signed[:user_name]

travel 2.hours
assert_equal "assain", cookies.signed[:user_name]
end

def test_encrypted_cookie_with_expires_set_relatively
cookies.encrypted[:user_name] = { value: "assain", expires: 2.hours }

Expand All @@ -1293,6 +1305,18 @@ def test_encrypted_cookie_with_expires_set_relatively
assert_nil cookies.encrypted[:user_name]
end

def test_encrypted_cookie_does_not_embed_expiration_if_config_is_set_to_false
@request.env['action_dispatch.use_authenticated_cookie_encryption'] = false

cookies.encrypted[:user_name] = { value: "assain", expires: 2.hours }

travel 1.hour
assert_equal "assain", cookies.encrypted[:user_name]

travel 2.hours
assert_equal "assain", cookies.encrypted[:user_name]
end

def test_vanilla_cookie_with_expires_set_relatively
travel_to Time.utc(2017, 8, 15) do
get :cookie_expires_in_two_hours
Expand Down
4 changes: 4 additions & 0 deletions guides/source/configuring.md
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,10 @@ Defaults to `'signed cookie'`.
* `config.action_dispatch.cookies_rotations` allows rotating
secrets, ciphers, and digests for encrypted and signed cookies.

* `config.action_dispatch.use_authenticated_cookie_encryption` controls encrypted cookies to use AES-256-GC
authenticated encryption and if signed and encrypted cookies are going to embed the expiry information
in the value. It defaults to `false`.

* `config.action_dispatch.perform_deep_munge` configures whether `deep_munge`
method should be performed on the parameters. See [Security Guide](security.html#unsafe-query-generation)
for more information. It defaults to `true`.
Expand Down
11 changes: 11 additions & 0 deletions guides/source/upgrading_ruby_on_rails.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,17 @@ Rails 5.2 adds bootsnap gem in the [newly generated app's Gemfile](https://githu
The `app:update` task sets it up in `boot.rb`. If you want to use it, then add it in the Gemfile,
otherwise change the `boot.rb` to not use bootsnap.

### Expiry in signed or encrypted cookie is now embedded in the cookies values

To improve security, Rails now embeds the expiry information also in encrypted or signed cookies value.

This new embed information make those cookies incompatible with versions of Rails older than 5.2.

If you require your cookies to be read by 5.1 and older, or you are still validating your 5.2 deploy and want
to allow you to rollback set
`Rails.application.config.action_dispatch.use_authenticated_cookie_encryption` to `false`.


Upgrading from Rails 5.0 to Rails 5.1
-------------------------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
# Rails.application.config.active_record.cache_versioning = true

# Use AES-256-GCM authenticated encryption for encrypted cookies.
# Also, embed cookie expiry in signed or encrypted cookies for increased security.
#
# This option is not backwards compatible with earlier Rails versions.
# It's best enabled when your entire app is migrated and stable on 5.2.
#
# Existing cookies will be converted on read then written with the new scheme.
# Rails.application.config.action_dispatch.use_authenticated_cookie_encryption = true

Expand Down

0 comments on commit b25fcbc

Please sign in to comment.