mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Allow a proc to be used in addition to a static value for cookies_same_site_protection
Add documentation of Proc usage for SameSite property to configuring.md Address PR comments Co-authored-by: Adrianna Chang <adrianna.chang@shopify.com>
This commit is contained in:
parent
c774da7ebe
commit
7459672fb0
4 changed files with 43 additions and 8 deletions
|
@ -70,7 +70,7 @@ module ActionDispatch
|
||||||
end
|
end
|
||||||
|
|
||||||
def cookies_same_site_protection
|
def cookies_same_site_protection
|
||||||
get_header Cookies::COOKIES_SAME_SITE_PROTECTION
|
get_header(Cookies::COOKIES_SAME_SITE_PROTECTION) || Proc.new { }
|
||||||
end
|
end
|
||||||
|
|
||||||
def cookies_digest
|
def cookies_digest
|
||||||
|
@ -444,7 +444,9 @@ module ActionDispatch
|
||||||
end
|
end
|
||||||
|
|
||||||
options[:path] ||= "/"
|
options[:path] ||= "/"
|
||||||
options[:same_site] ||= request.cookies_same_site_protection
|
|
||||||
|
cookies_same_site_protection = request.cookies_same_site_protection
|
||||||
|
options[:same_site] ||= cookies_same_site_protection.call(request)
|
||||||
|
|
||||||
if options[:domain] == :all || options[:domain] == "all"
|
if options[:domain] == :all || options[:domain] == "all"
|
||||||
# If there is a provided tld length then we use it otherwise default domain regexp.
|
# If there is a provided tld length then we use it otherwise default domain regexp.
|
||||||
|
|
|
@ -358,20 +358,41 @@ class CookiesTest < ActionController::TestCase
|
||||||
@request.env["action_dispatch.encrypted_signed_cookie_salt"] = ENCRYPTED_SIGNED_COOKIE_SALT
|
@request.env["action_dispatch.encrypted_signed_cookie_salt"] = ENCRYPTED_SIGNED_COOKIE_SALT
|
||||||
@request.env["action_dispatch.authenticated_encrypted_cookie_salt"] = AUTHENTICATED_ENCRYPTED_COOKIE_SALT
|
@request.env["action_dispatch.authenticated_encrypted_cookie_salt"] = AUTHENTICATED_ENCRYPTED_COOKIE_SALT
|
||||||
|
|
||||||
@request.env["action_dispatch.cookies_same_site_protection"] = :lax
|
@request.env["action_dispatch.cookies_same_site_protection"] = proc { :lax }
|
||||||
@request.host = "www.nextangle.com"
|
@request.host = "www.nextangle.com"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_setting_cookie_with_no_protection
|
def test_setting_cookie_with_no_protection
|
||||||
@request.env["action_dispatch.cookies_same_site_protection"] = :none
|
@request.env["action_dispatch.cookies_same_site_protection"] = proc { :none }
|
||||||
|
|
||||||
get :authenticate
|
get :authenticate
|
||||||
assert_cookie_header "user_name=david; path=/; SameSite=None"
|
assert_cookie_header "user_name=david; path=/; SameSite=None"
|
||||||
assert_equal({ "user_name" => "david" }, @response.cookies)
|
assert_equal({ "user_name" => "david" }, @response.cookies)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_setting_cookie_with_protection_proc_normal_user_agent
|
||||||
|
@request.env["action_dispatch.cookies_same_site_protection"] = Proc.new do |request|
|
||||||
|
:strict unless request.user_agent == "spooky browser"
|
||||||
|
end
|
||||||
|
|
||||||
|
get :authenticate
|
||||||
|
assert_cookie_header "user_name=david; path=/; SameSite=Strict"
|
||||||
|
assert_equal({ "user_name" => "david" }, @response.cookies)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_setting_cookie_with_protection_proc_special_user_agent
|
||||||
|
@request.env["action_dispatch.cookies_same_site_protection"] = Proc.new do |request|
|
||||||
|
:strict unless request.user_agent == "spooky browser"
|
||||||
|
end
|
||||||
|
|
||||||
|
request.user_agent = "spooky browser"
|
||||||
|
get :authenticate
|
||||||
|
assert_cookie_header "user_name=david; path=/"
|
||||||
|
assert_equal({ "user_name" => "david" }, @response.cookies)
|
||||||
|
end
|
||||||
|
|
||||||
def test_setting_cookie_with_misspelled_protection_raises
|
def test_setting_cookie_with_misspelled_protection_raises
|
||||||
@request.env["action_dispatch.cookies_same_site_protection"] = :funky
|
@request.env["action_dispatch.cookies_same_site_protection"] = proc { :funky }
|
||||||
|
|
||||||
error = assert_raise ArgumentError do
|
error = assert_raise ArgumentError do
|
||||||
get :authenticate
|
get :authenticate
|
||||||
|
@ -380,7 +401,7 @@ class CookiesTest < ActionController::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_setting_cookie_with_strict
|
def test_setting_cookie_with_strict
|
||||||
@request.env["action_dispatch.cookies_same_site_protection"] = :strict
|
@request.env["action_dispatch.cookies_same_site_protection"] = proc { :strict }
|
||||||
|
|
||||||
get :authenticate
|
get :authenticate
|
||||||
assert_cookie_header "user_name=david; path=/; SameSite=Strict"
|
assert_cookie_header "user_name=david; path=/; SameSite=Strict"
|
||||||
|
|
|
@ -629,7 +629,15 @@ Defaults to `'signed cookie'`.
|
||||||
|
|
||||||
* `config.action_dispatch.cookies_same_site_protection` configures the default
|
* `config.action_dispatch.cookies_same_site_protection` configures the default
|
||||||
value of the `SameSite` attribute when setting cookies. When set to `nil`, the
|
value of the `SameSite` attribute when setting cookies. When set to `nil`, the
|
||||||
`SameSite` attribute is not added.
|
`SameSite` attribute is not added. To allow the value of the `SameSite` attribute
|
||||||
|
to be configured dynamically based on the request, a proc may be specified.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
config.action_dispatch.cookies_same_site_protection = ->(request) do
|
||||||
|
:strict unless request.user_agent == "TestAgent"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
* `config.action_dispatch.ssl_default_redirect_status` configures the default
|
* `config.action_dispatch.ssl_default_redirect_status` configures the default
|
||||||
HTTP status code used when redirecting non-GET/HEAD requests from HTTP to HTTPS
|
HTTP status code used when redirecting non-GET/HEAD requests from HTTP to HTTPS
|
||||||
|
|
|
@ -281,7 +281,7 @@ module Rails
|
||||||
"action_dispatch.cookies_serializer" => config.action_dispatch.cookies_serializer,
|
"action_dispatch.cookies_serializer" => config.action_dispatch.cookies_serializer,
|
||||||
"action_dispatch.cookies_digest" => config.action_dispatch.cookies_digest,
|
"action_dispatch.cookies_digest" => config.action_dispatch.cookies_digest,
|
||||||
"action_dispatch.cookies_rotations" => config.action_dispatch.cookies_rotations,
|
"action_dispatch.cookies_rotations" => config.action_dispatch.cookies_rotations,
|
||||||
"action_dispatch.cookies_same_site_protection" => config.action_dispatch.cookies_same_site_protection,
|
"action_dispatch.cookies_same_site_protection" => coerce_same_site_protection(config.action_dispatch.cookies_same_site_protection),
|
||||||
"action_dispatch.use_cookies_with_metadata" => config.action_dispatch.use_cookies_with_metadata,
|
"action_dispatch.use_cookies_with_metadata" => config.action_dispatch.use_cookies_with_metadata,
|
||||||
"action_dispatch.content_security_policy" => config.content_security_policy,
|
"action_dispatch.content_security_policy" => config.content_security_policy,
|
||||||
"action_dispatch.content_security_policy_report_only" => config.content_security_policy_report_only,
|
"action_dispatch.content_security_policy_report_only" => config.content_security_policy_report_only,
|
||||||
|
@ -628,5 +628,9 @@ module Rails
|
||||||
def build_middleware
|
def build_middleware
|
||||||
config.app_middleware + super
|
config.app_middleware + super
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def coerce_same_site_protection(protection)
|
||||||
|
protection.respond_to?(:call) ? protection : proc { protection }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue