File tree 3 files changed +35
-1
lines changed
lib/action_dispatch/session
3 files changed +35
-1
lines changed Original file line number Diff line number Diff line change @@ -38,6 +38,12 @@ been updated in the last 30 days. The 30 days cutoff can be changed using the
38
38
Configuration
39
39
--------------
40
40
41
+ Disable fallback to use insecure session by providing the option ` secure_session_only `
42
+ when setting up the session store.
43
+ ``` ruby
44
+ Rails .application.config.session_store :active_record_store , :key => ' _my_app_session' , :secure_session_only => true
45
+ ```
46
+
41
47
The default assumes a ` sessions ` table with columns:
42
48
43
49
* ` id ` (numeric primary key),
Original file line number Diff line number Diff line change @@ -60,6 +60,11 @@ class ActiveRecordStore < ActionDispatch::Session::AbstractSecureStore
60
60
SESSION_RECORD_KEY = 'rack.session.record'
61
61
ENV_SESSION_OPTIONS_KEY = Rack ::RACK_SESSION_OPTIONS
62
62
63
+ def initialize ( app , options = { } )
64
+ @secure_session_only = options . delete ( :secure_session_only ) { false }
65
+ super ( app , options )
66
+ end
67
+
63
68
private
64
69
def get_session ( request , sid )
65
70
logger . silence do
@@ -136,7 +141,7 @@ def get_session_with_fallback(sid)
136
141
if sid && !self . class . private_session_id? ( sid . public_id )
137
142
if ( secure_session = session_class . find_by_session_id ( sid . private_id ) )
138
143
secure_session
139
- elsif ( insecure_session = session_class . find_by_session_id ( sid . public_id ) )
144
+ elsif ! @secure_session_only && ( insecure_session = session_class . find_by_session_id ( sid . public_id ) )
140
145
insecure_session . session_id = sid . private_id # this causes the session to be secured
141
146
insecure_session
142
147
end
Original file line number Diff line number Diff line change @@ -305,6 +305,29 @@ def test_session_store_with_all_domains
305
305
end
306
306
end
307
307
308
+ define_method :"test_unsecured_sessions_are_ignored_when_insecure_fallback_is_disabled_#{ class_name } " do
309
+ with_store ( class_name ) do
310
+ with_test_route_set ( secure_session_only : true ) do
311
+ get '/set_session_value' , params : { foo : 'baz' }
312
+ assert_response :success
313
+ public_session_id = cookies [ '_session_id' ]
314
+
315
+ session = ActiveRecord ::SessionStore ::Session . last
316
+ session . data # otherwise we cannot save
317
+ session . session_id = public_session_id
318
+ session . save!
319
+
320
+ get '/get_session_value'
321
+ assert_response :success
322
+
323
+ session . reload
324
+ new_session = ActiveRecord ::SessionStore ::Session . last
325
+ assert_not_equal public_session_id , new_session . session_id
326
+ assert_not_equal session . session_id , new_session . session_id
327
+ end
328
+ end
329
+ end
330
+
308
331
# to avoid a different kind of timing attack
309
332
define_method :"test_sessions_cannot_be_retrieved_by_their_private_session_id_for_#{ class_name } " do
310
333
with_store ( class_name ) do
You can’t perform that action at this time.
0 commit comments