From abb6b624106ef6cee5a6a13083087da22236f277 Mon Sep 17 00:00:00 2001 From: John R McGarvey Date: Wed, 6 Mar 2024 15:21:24 -0500 Subject: [PATCH] Introduce `assume_ssl` option to allow secure session cookies through insecure proxy (#41) --- lib/rack/session/abstract/id.rb | 3 ++- test/spec_session_abstract_persisted.rb | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/rack/session/abstract/id.rb b/lib/rack/session/abstract/id.rb index a7d7747..f32bad5 100644 --- a/lib/rack/session/abstract/id.rb +++ b/lib/rack/session/abstract/id.rb @@ -257,6 +257,7 @@ def initialize(app, options = {}) @app = app @default_options = self.class::DEFAULT_OPTIONS.merge(options) @key = @default_options.delete(:key) + @assume_ssl = @default_options.delete(:assume_ssl) @cookie_only = @default_options.delete(:cookie_only) @same_site = @default_options.delete(:same_site) initialize_sid @@ -368,7 +369,7 @@ def force_options?(options) def security_matches?(request, options) return true unless options[:secure] - request.ssl? + request.ssl? || @assume_ssl == true end # Acquires the session from the environment and the session id from diff --git a/test/spec_session_abstract_persisted.rb b/test/spec_session_abstract_persisted.rb index b7040be..021791a 100644 --- a/test/spec_session_abstract_persisted.rb +++ b/test/spec_session_abstract_persisted.rb @@ -68,4 +68,28 @@ def session_exists?(req) it "#delete_session raises" do proc { @pers.send(:delete_session, nil, nil, nil) }.must_raise RuntimeError end + + describe '#security_matches?' do + + it '#security_matches? returns true if secure cookie is off' do + @pers.send(:security_matches?, Rack::Request.new({}), {}).must_equal true + end + + it '#security_matches? returns true if ssl is on' do + req = Rack::Request.new({}) + req.set_header('HTTPS', 'on') + @pers.send(:security_matches?, req, { secure: true }).must_equal true + end + + it '#security_matches? returns true if assume_ssl option is set' do + req = Rack::Request.new({}) + pers_with_persist = @class.new(nil, { assume_ssl: true }) + pers_with_persist.send(:security_matches?, req, { secure: true }).must_equal true + end + + it '#security_matches? returns false if secure cookie is on, but not ssl or assume_ssl' do + @pers.send(:security_matches?, Rack::Request.new({}), { secure: true }).must_equal false + end + + end end