Drop Remember-me cookie's Expires when the box is unchecked
Without Remember-me the session cookie was still being written via `cookies.signed.permanent`, so it survived browser restart on shared devices — surprising for a user who explicitly opted out of Remember-me. Issue a browser-session cookie (no Expires) when remember_me is off; the server-side Session#expires_at still bounds the 24h / 30d window. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -73,7 +73,15 @@ module Authentication
|
||||
# Set domain for cross-subdomain authentication if we can extract it
|
||||
cookie_options[:domain] = domain if domain.present?
|
||||
|
||||
cookies.signed.permanent[:session_id] = cookie_options
|
||||
# When "Remember me" is off, issue a browser-session cookie (no Expires)
|
||||
# so closing the browser signs the user out — especially important on
|
||||
# shared devices. The server Session#expires_at still enforces the
|
||||
# 24h / 30d window regardless.
|
||||
if remember_me
|
||||
cookies.signed.permanent[:session_id] = cookie_options
|
||||
else
|
||||
cookies.signed[:session_id] = cookie_options
|
||||
end
|
||||
|
||||
# Create a one-time token for immediate forward auth after authentication
|
||||
# This solves the race condition where browser hasn't processed cookie yet
|
||||
|
||||
@@ -30,4 +30,22 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
|
||||
assert_redirected_to signin_path
|
||||
assert_empty cookies[:session_id]
|
||||
end
|
||||
|
||||
test "session cookie has no Expires attribute when remember_me is off" do
|
||||
post session_path, params: {email_address: @user.email_address, password: "password", remember_me: "0"}
|
||||
|
||||
set_cookie = Array(response.headers["Set-Cookie"]).find { |c| c.start_with?("session_id=") }
|
||||
assert set_cookie, "session_id cookie should be set"
|
||||
refute_match(/expires=/i, set_cookie,
|
||||
"without Remember me, the session cookie must be a browser-session cookie (no Expires)")
|
||||
end
|
||||
|
||||
test "session cookie has long-lived Expires attribute when remember_me is on" do
|
||||
post session_path, params: {email_address: @user.email_address, password: "password", remember_me: "1"}
|
||||
|
||||
set_cookie = Array(response.headers["Set-Cookie"]).find { |c| c.start_with?("session_id=") }
|
||||
assert set_cookie, "session_id cookie should be set"
|
||||
assert_match(/expires=/i, set_cookie,
|
||||
"with Remember me, the cookie should have an Expires attribute")
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user