New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Purpose Metadata to Cookies #32937

Merged
merged 1 commit into from Aug 12, 2018

Conversation

Projects
None yet
8 participants
@assain
Contributor

assain commented May 20, 2018

Summary
This PR adds purpose metadata to cookies so that the value of one cookie cannot be copied and used as the value of another cookie.

Other Information
Turn on config.action_dispatch.use_cookies_with_metadata to embed expiry and purpose metadata inside signed/encrypted cookies, and to verify if signed/encrypted cookie values have been copy-pasted. Previously set cookies (i.e. without purpose or expiry metadata) will continue to be honored.

@rails-bot

This comment has been minimized.

Show comment
Hide comment
@rails-bot

rails-bot May 20, 2018

r? @georgeclaghorn

(@rails-bot has picked a reviewer for you, use r? to override)

rails-bot commented May 20, 2018

r? @georgeclaghorn

(@rails-bot has picked a reviewer for you, use r? to override)

@assain

This comment has been minimized.

Show comment
Hide comment
@assain
Contributor

assain commented May 20, 2018

@rails-bot rails-bot assigned kaspth and unassigned georgeclaghorn May 20, 2018

Show outdated Hide outdated actionpack/test/dispatch/cookies_test.rb
Show outdated Hide outdated actionpack/test/dispatch/cookies_test.rb
Show outdated Hide outdated actionpack/test/dispatch/cookies_test.rb
Show outdated Hide outdated actionpack/test/dispatch/cookies_test.rb

@assain assain changed the title from Add purpose metadata to cookies. to Add Purpose Metadata to Cookies Jun 8, 2018

@mikeycgto

Looks great overall! Nice work!!

Show outdated Hide outdated actionpack/lib/action_dispatch/middleware/cookies.rb
Show outdated Hide outdated actionpack/lib/action_dispatch/middleware/cookies.rb
Show outdated Hide outdated .../app/templates/config/initializers/handle_cookies_without_metadata.rb.tt
Show outdated Hide outdated .../app/templates/config/initializers/handle_cookies_without_metadata.rb.tt
@kaspth

Initial pass! Looks like this mostly gets the job done, but the flow and readability isn't quite where we need it. But that's good! Now we have a base to expand on.

Left lots of questions to hopefully guide you in your further decision making.

Show outdated Hide outdated actionpack/test/dispatch/cookies_test.rb
Show outdated Hide outdated .../app/templates/config/initializers/handle_cookies_without_metadata.rb.tt
Show outdated Hide outdated .../app/templates/config/initializers/handle_cookies_without_metadata.rb.tt
Show outdated Hide outdated .../app/templates/config/initializers/handle_cookies_without_metadata.rb.tt
Show outdated Hide outdated actionpack/lib/action_dispatch/middleware/cookies.rb
Show outdated Hide outdated actionpack/lib/action_dispatch/middleware/cookies.rb
Show outdated Hide outdated actionpack/lib/action_dispatch/middleware/cookies.rb
Show outdated Hide outdated actionpack/lib/action_dispatch/middleware/cookies.rb
Show outdated Hide outdated actionpack/lib/action_dispatch/middleware/cookies.rb
Show outdated Hide outdated actionpack/lib/action_dispatch/middleware/cookies.rb
@assain

This comment has been minimized.

Show comment
Hide comment
@assain

assain Jun 18, 2018

Contributor

@kaspth Here's the suggested changes 😄

Contributor

assain commented Jun 18, 2018

@kaspth Here's the suggested changes 😄

Show outdated Hide outdated actionpack/lib/action_dispatch/railtie.rb
@sikachu

I do feel weird about having a hash ({ switch_on: true }) as a way to enable the feature. Is there a particular reason why we can't make falsy as an off state and any object as an on state?

i.e.

.cookies_with_purpose_metadata = false # off
.cookies_with_purpose_metadata = true # on, `honor_cookies_without_metadata_till` is nil
.cookies_with_purpose_metadata = { honor_cookies_without_metadata_till: 30.days.from_now }

Also, I'm curious about the wording of honor_cookies_without_metadata_till. I think expanding till to until would make it reads better, and maybe we can change honor to allow to, just to make it more inline of other flags that available in Rails (assuming it still conveys the same message):

config.action_dispatch.cookies_with_purpose_metadata = {
  allow_cookies_without_metadata_until: 30.days.from_now
}

Please let me know what you think. Thank you for your patch.

Show outdated Hide outdated ...rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt
@kaspth

Nice! This got a lot cleaner 👏

I was just about to ask you to kill the extra grace period option — then you went and did it on your own! 😄

Show outdated Hide outdated actionpack/lib/action_dispatch/middleware/cookies.rb
Show outdated Hide outdated actionpack/lib/action_dispatch/middleware/cookies.rb
Show outdated Hide outdated actionpack/lib/action_dispatch/middleware/cookies.rb
Show outdated Hide outdated actionpack/lib/action_dispatch/middleware/cookies.rb
Show outdated Hide outdated ...rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt
Show outdated Hide outdated ...rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt
Show outdated Hide outdated actionpack/lib/action_dispatch/middleware/cookies.rb
@assain

This comment has been minimized.

Show comment
Hide comment
@assain

assain Jul 6, 2018

Contributor

@kaspth @sikachu here are the suggested changes!

Contributor

assain commented Jul 6, 2018

@kaspth @sikachu here are the suggested changes!

Show outdated Hide outdated actionpack/lib/action_dispatch/middleware/cookies.rb
Show outdated Hide outdated actionpack/lib/action_dispatch/middleware/cookies.rb
#
# This option is not backwards compatible with earlier Rails versions.
# It's best enabled when your entire app is migrated and stable on 6.0.
# Rails.application.config.action_dispatch.use_cookies_with_metadata = true

This comment has been minimized.

@kaspth

kaspth Jul 7, 2018

Member

It's still not clear to me how this meshes with use_authenticated_cookie_encryption that's on 5-2-stable:

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

What should users who upgrade do? And what happens to their cookies, with and without the 5-2-stable flag enabled?

Perhaps you can try some testing on a 5.2 generated app that you upgrade to Rails 6?

Some tips for dev apps:

git checkout 5-2-stable # In your Rails checkout
cd ~ # Or wherever you keep your code
path/to/rails/exe/rails new cookie --dev # Generates the app with your Rails checkout (check the Gemfile), then you should be able to do `git checkout your-branch` in Rails.
@kaspth

kaspth Jul 7, 2018

Member

It's still not clear to me how this meshes with use_authenticated_cookie_encryption that's on 5-2-stable:

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

What should users who upgrade do? And what happens to their cookies, with and without the 5-2-stable flag enabled?

Perhaps you can try some testing on a 5.2 generated app that you upgrade to Rails 6?

Some tips for dev apps:

git checkout 5-2-stable # In your Rails checkout
cd ~ # Or wherever you keep your code
path/to/rails/exe/rails new cookie --dev # Generates the app with your Rails checkout (check the Gemfile), then you should be able to do `git checkout your-branch` in Rails.

This comment has been minimized.

@assain

assain Jul 11, 2018

Contributor

@kaspth

When users upgrade their apps, use_cookies_with_metadata is false until they uncomment the config in the new_framework_defaults.rb.tt or load them in application.config, given this information, there are two cases here:

i) 5-2-Stable flag is enabled:
These cookies are written in the new format with expiry and purpose (is nil) embedded. And since purpose checking is off, these cookies are readable on Rails 6.0.

ii) 5-2-Stable flag is disabled:
These are not AEAD cookies nor do they have expiry and purpose embedded. Since they are converted to AEAD cookies on cookie-read, they are readable too.

@assain

assain Jul 11, 2018

Contributor

@kaspth

When users upgrade their apps, use_cookies_with_metadata is false until they uncomment the config in the new_framework_defaults.rb.tt or load them in application.config, given this information, there are two cases here:

i) 5-2-Stable flag is enabled:
These cookies are written in the new format with expiry and purpose (is nil) embedded. And since purpose checking is off, these cookies are readable on Rails 6.0.

ii) 5-2-Stable flag is disabled:
These are not AEAD cookies nor do they have expiry and purpose embedded. Since they are converted to AEAD cookies on cookie-read, they are readable too.

Show outdated Hide outdated ...rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt
Show outdated Hide outdated railties/test/application/middleware/session_test.rb
Show outdated Hide outdated actionpack/lib/action_dispatch/middleware/cookies.rb
Purpose Metadata For Signed And Encrypted Cookies
Purpose metadata prevents cookie values from being
copy-pasted and ensures that the cookie is used only
for its originally intended purpose.

The Purpose and Expiry metadata are embedded inside signed/encrypted
cookies and will not be readable on previous versions of Rails.

We can switch off purpose and expiry metadata embedded in
signed and encrypted cookies using

	config.action_dispatch.use_cookies_with_metadata = false

if you want your cookies to be readable on older versions of Rails.
@kaspth

kaspth approved these changes Aug 12, 2018

❤️👏

Let's clean up the test things and add a changelog in a separate PR. I don't want to hold this up any longer 😄

assert_equal "5-2-Stable Chocolate Cookies", cookies.encrypted[:favorite]
freeze_time do
travel 1001.years

This comment has been minimized.

@kaspth

kaspth Aug 12, 2018

Member

freeze_time just does travel_to Time.now, so you could just do travel 1001.years do.

@kaspth

kaspth Aug 12, 2018

Member

freeze_time just does travel_to Time.now, so you could just do travel 1001.years do.

@kaspth kaspth merged commit 14d3c7c into rails:master Aug 12, 2018

2 checks passed

codeclimate All good!
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details

bogdanvlviv added a commit to bogdanvlviv/rails that referenced this pull request Aug 30, 2018

Add info about `config.action_dispatch.use_cookies_with_metadata` to …
…"Configuring Rails Applications" guide [ci skip]

Related to #32937, #33605.

bogdanvlviv added a commit to bogdanvlviv/rails that referenced this pull request Aug 30, 2018

kamipo added a commit that referenced this pull request Aug 30, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment