From 8746e961ef4013094bfa7665c0f6c86b7da1981b Mon Sep 17 00:00:00 2001 From: Timo Date: Tue, 31 Mar 2020 22:08:26 +1300 Subject: [PATCH] Allow SameSite cookie attribute to be set (#37) * Allow SameSite cookie attribute to be set Why: Changes to how browsers will handle the default SameSite attribute means it's generally considered better to explicitely set it. Lax is what browsers will default to. Further reading: https://www.chromium.org/updates/same-site https://tools.ietf.org/html/draft-west-cookie-incrementalism-00 https://web.dev/samesite-cookie-recipes/ * Automatically set cookie to Secure if SameSite is set to None. --- README.md | 14 ++++++++++++ lib/angular_rails_csrf/concern.rb | 8 +++++-- test/angular_rails_csrf_test.rb | 38 +++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8014213..3edd589 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,20 @@ end `angular_rails_csrf_secure` defaults to `false`. +### SameSite + +The SameSite attribute now defaults to `:lax`. You can override this in the config: + +```ruby +# application.rb +class Application < Rails::Application + #... + config.angular_rails_csrf_same_site = :strict +end +``` + +**NOTE**: When using `SameSite=None`, this gem automatically sets the cookie to `Secure`. + ### Exclusions Sometimes you will want to skip setting the XSRF token for certain controllers (for example, when using SSE or ActionCable, as discussed [here](https://github.com/jsanders/angular_rails_csrf/issues/7)): diff --git a/lib/angular_rails_csrf/concern.rb b/lib/angular_rails_csrf/concern.rb index e91fc77..f73b522 100644 --- a/lib/angular_rails_csrf/concern.rb +++ b/lib/angular_rails_csrf/concern.rb @@ -13,11 +13,15 @@ def set_xsrf_token_cookie config = Rails.application.config + same_site = config.respond_to?(:angular_rails_csrf_same_site) ? config.angular_rails_csrf_same_site : :lax + secure = config.angular_rails_csrf_secure if config.respond_to?(:angular_rails_csrf_secure) + cookie_options = { value: form_authenticity_token, - domain: config.respond_to?(:angular_rails_csrf_domain) ? config.angular_rails_csrf_domain : nil + domain: config.respond_to?(:angular_rails_csrf_domain) ? config.angular_rails_csrf_domain : nil, + same_site: same_site, + secure: same_site == :none || secure } - cookie_options[:secure] = config.angular_rails_csrf_secure if config.respond_to?(:angular_rails_csrf_secure) cookie_name = config.respond_to?(:angular_rails_csrf_cookie_name) ? config.angular_rails_csrf_cookie_name : 'XSRF-TOKEN' cookies[cookie_name] = cookie_options diff --git a/test/angular_rails_csrf_test.rb b/test/angular_rails_csrf_test.rb index ec52318..278e301 100644 --- a/test/angular_rails_csrf_test.rb +++ b/test/angular_rails_csrf_test.rb @@ -73,6 +73,44 @@ def config.angular_rails_csrf_domain end end + test 'same_site is set to Lax by default' do + get :index + assert @response.headers['Set-Cookie'].include?('SameSite=Lax') + assert_valid_cookie + assert_response :success + end + + test 'same_site can be configured' do + begin + config = Rails.application.config + config.define_singleton_method(:angular_rails_csrf_same_site) { :strict } + + get :index + assert @response.headers['Set-Cookie'].include?('SameSite=Strict') + assert_valid_cookie + assert_response :success + ensure + config.instance_eval('undef :angular_rails_csrf_same_site', __FILE__, __LINE__) + end + end + + test 'secure is set automatically when same_site is set to none' do + begin + @request.headers['HTTPS'] = 'on' + + config = Rails.application.config + config.define_singleton_method(:angular_rails_csrf_same_site) { :none } + + get :index + assert @response.headers['Set-Cookie'].include?('SameSite=None') + assert @response.headers['Set-Cookie'].include?('secure') + assert_valid_cookie + assert_response :success + ensure + config.instance_eval('undef :angular_rails_csrf_same_site', __FILE__, __LINE__) + end + end + private # Helpers