Skip to content

Commit 73909f4

Browse files
Merge pull request rails#45688 from jonathanhefner/session-cookies-default-same_site
Fix default `SameSite` for session cookies
2 parents 1adb617 + c95780d commit 73909f4

File tree

4 files changed

+36
-5
lines changed

4 files changed

+36
-5
lines changed

actionpack/lib/action_dispatch/middleware/cookies.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def cookies_serializer
7070
end
7171

7272
def cookies_same_site_protection
73-
get_header(Cookies::COOKIES_SAME_SITE_PROTECTION) || Proc.new { }
73+
get_header(Cookies::COOKIES_SAME_SITE_PROTECTION)&.call(self)
7474
end
7575

7676
def cookies_digest
@@ -454,7 +454,7 @@ def handle_options(options)
454454
options[:path] ||= "/"
455455

456456
unless options.key?(:same_site)
457-
options[:same_site] = request.cookies_same_site_protection.call(request)
457+
options[:same_site] = request.cookies_same_site_protection
458458
end
459459

460460
if options[:domain] == :all || options[:domain] == "all"

actionpack/lib/action_dispatch/middleware/session/cookie_store.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,12 @@ def initialize(session_id, cookie_value = {})
5656
end
5757
end
5858

59+
DEFAULT_SAME_SITE = proc { |request| request.cookies_same_site_protection } # :nodoc:
60+
5961
def initialize(app, options = {})
60-
super(app, options.merge!(cookie_only: true))
62+
options[:cookie_only] = true
63+
options[:same_site] = DEFAULT_SAME_SITE if !options.key?(:same_site)
64+
super
6165
end
6266

6367
def delete_session(req, session_id, options)

actionpack/test/dispatch/session/cookie_store_test.rb

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ class CookieStoreTest < ActionDispatch::IntegrationTest
1313
Generator = ActiveSupport::KeyGenerator.new(SessionSecret, iterations: 1000)
1414
Rotations = ActiveSupport::Messages::RotationConfiguration.new
1515

16+
SameSite = proc { :lax }
17+
1618
Encryptor = ActiveSupport::MessageEncryptor.new(
1719
Generator.generate_key(SessionSalt, 32), cipher: "aes-256-gcm", serializer: Marshal
1820
)
@@ -379,8 +381,29 @@ def test_session_store_with_all_domains
379381
end
380382
end
381383

384+
test "default same_site derives SameSite from env" do
385+
with_test_route_set do
386+
get "/set_session_value"
387+
assert_match %r/SameSite=Lax/, headers["Set-Cookie"]
388+
end
389+
end
390+
391+
test "explicit same_site sets SameSite" do
392+
with_test_route_set(same_site: :strict) do
393+
get "/set_session_value"
394+
assert_match %r/SameSite=Strict/, headers["Set-Cookie"]
395+
end
396+
end
397+
398+
test "explicit nil same_site omits SameSite" do
399+
with_test_route_set(same_site: nil) do
400+
get "/set_session_value"
401+
assert_no_match %r/SameSite=/, headers["Set-Cookie"]
402+
end
403+
end
404+
382405
private
383-
# Overwrite get to send SessionSecret in env hash
406+
# Overwrite `get` to set env hash
384407
def get(path, **options)
385408
options[:headers] ||= {}
386409
options[:headers].tap do |config|
@@ -390,6 +413,8 @@ def get(path, **options)
390413

391414
config["action_dispatch.key_generator"] ||= Generator
392415
config["action_dispatch.cookies_rotations"] ||= Rotations
416+
417+
config["action_dispatch.cookies_same_site_protection"] ||= SameSite
393418
end
394419

395420
super

railties/test/application/configuration_test.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1670,7 +1670,9 @@ def index
16701670
make_basic_app
16711671

16721672
assert_equal ActionDispatch::Session::CookieStore, app.config.session_store
1673-
assert_equal session_options, app.config.session_options
1673+
session_options.each do |key, value|
1674+
assert_equal value, app.config.session_options[key]
1675+
end
16741676
end
16751677

16761678
test "config.log_level defaults to debug in development" do

0 commit comments

Comments
 (0)