diff options
Diffstat (limited to 'railties/test/application/middleware/session_test.rb')
-rw-r--r-- | railties/test/application/middleware/session_test.rb | 133 |
1 files changed, 111 insertions, 22 deletions
diff --git a/railties/test/application/middleware/session_test.rb b/railties/test/application/middleware/session_test.rb index 959a629ede..a17988235a 100644 --- a/railties/test/application/middleware/session_test.rb +++ b/railties/test/application/middleware/session_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "isolation/abstract_unit" require "rack/test" @@ -162,6 +164,11 @@ module ApplicationTests end RUBY + add_to_config <<-RUBY + # Enable AEAD cookies + config.action_dispatch.use_authenticated_cookie_encryption = true + RUBY + require "#{app_path}/config/environment" get "/foo/write_session" @@ -171,9 +178,9 @@ module ApplicationTests get "/foo/read_encrypted_cookie" assert_equal "1", last_response.body - secret = app.key_generator.generate_key("encrypted cookie") - sign_secret = app.key_generator.generate_key("signed encrypted cookie") - encryptor = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len], sign_secret) + cipher = "aes-256-gcm" + secret = app.key_generator.generate_key("authenticated encrypted cookie") + encryptor = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len(cipher)], cipher: cipher) get "/foo/read_raw_cookie" assert_equal 1, encryptor.decrypt_and_verify(last_response.body)["foo"] @@ -209,6 +216,9 @@ module ApplicationTests add_to_config <<-RUBY secrets.secret_token = "3b7cd727ee24e8444053437c36cc66c4" + + # Enable AEAD cookies + config.action_dispatch.use_authenticated_cookie_encryption = true RUBY require "#{app_path}/config/environment" @@ -220,9 +230,9 @@ module ApplicationTests get "/foo/read_encrypted_cookie" assert_equal "1", last_response.body - secret = app.key_generator.generate_key("encrypted cookie") - sign_secret = app.key_generator.generate_key("signed encrypted cookie") - encryptor = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len], sign_secret) + cipher = "aes-256-gcm" + secret = app.key_generator.generate_key("authenticated encrypted cookie") + encryptor = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len(cipher)], cipher: cipher) get "/foo/read_raw_cookie" assert_equal 1, encryptor.decrypt_and_verify(last_response.body)["foo"] @@ -264,6 +274,9 @@ module ApplicationTests add_to_config <<-RUBY secrets.secret_token = "3b7cd727ee24e8444053437c36cc66c4" + + # Enable AEAD cookies + config.action_dispatch.use_authenticated_cookie_encryption = true RUBY require "#{app_path}/config/environment" @@ -279,14 +292,84 @@ module ApplicationTests get "/foo/read_encrypted_cookie" assert_equal "2", last_response.body - secret = app.key_generator.generate_key("encrypted cookie") - sign_secret = app.key_generator.generate_key("signed encrypted cookie") - encryptor = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len], sign_secret) + cipher = "aes-256-gcm" + secret = app.key_generator.generate_key("authenticated encrypted cookie") + encryptor = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len(cipher)], cipher: cipher) get "/foo/read_raw_cookie" assert_equal 2, encryptor.decrypt_and_verify(last_response.body)["foo"] end + test "session upgrading from AES-CBC-HMAC encryption to AES-GCM encryption" do + app_file "config/routes.rb", <<-RUBY + Rails.application.routes.draw do + get ':controller(/:action)' + end + RUBY + + controller :foo, <<-RUBY + class FooController < ActionController::Base + def write_raw_session + # AES-256-CBC with SHA1 HMAC + # {"session_id"=>"1965d95720fffc123941bdfb7d2e6870", "foo"=>1} + cookies[:_myapp_session] = "TlgrdS85aUpDd1R2cDlPWlR6K0FJeGExckwySjZ2Z0pkR3d2QnRObGxZT25aalJWYWVvbFVLcHF4d0VQVDdSaFF2QjFPbG9MVjJzeWp3YjcyRUlKUUU2ZlR4bXlSNG9ZUkJPRUtld0E3dVU9LS0xNDZXbGpRZ3NjdW43N2haUEZJSUNRPT0=--3639b5ce54c09495cfeaae928cd5634e0c4b2e96" + head :ok + end + + def write_session + session[:foo] = session[:foo] + 1 + head :ok + end + + def read_session + render plain: session[:foo] + end + + def read_encrypted_cookie + render plain: cookies.encrypted[:_myapp_session]['foo'] + end + + def read_raw_cookie + render plain: cookies[:_myapp_session] + end + end + RUBY + + add_to_config <<-RUBY + # Use a static key + Rails.application.credentials.secret_key_base = "known key base" + + # Enable AEAD cookies + config.action_dispatch.use_authenticated_cookie_encryption = true + RUBY + + begin + old_rails_env, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], "production" + + require "#{app_path}/config/environment" + + get "/foo/write_raw_session" + get "/foo/read_session" + assert_equal "1", last_response.body + + get "/foo/write_session" + get "/foo/read_session" + assert_equal "2", last_response.body + + get "/foo/read_encrypted_cookie" + assert_equal "2", last_response.body + + cipher = "aes-256-gcm" + secret = app.key_generator.generate_key("authenticated encrypted cookie") + encryptor = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len(cipher)], cipher: cipher) + + get "/foo/read_raw_cookie" + assert_equal 2, encryptor.decrypt_and_verify(last_response.body)["foo"] + ensure + ENV["RAILS_ENV"] = old_rails_env + end + end + test "session upgrading legacy signed cookies to new signed cookies" do app_file "config/routes.rb", <<-RUBY Rails.application.routes.draw do @@ -323,26 +406,32 @@ module ApplicationTests add_to_config <<-RUBY secrets.secret_token = "3b7cd727ee24e8444053437c36cc66c4" - secrets.secret_key_base = nil + Rails.application.credentials.secret_key_base = nil RUBY - require "#{app_path}/config/environment" + begin + old_rails_env, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], "production" - get "/foo/write_raw_session" - get "/foo/read_session" - assert_equal "1", last_response.body + require "#{app_path}/config/environment" - get "/foo/write_session" - get "/foo/read_session" - assert_equal "2", last_response.body + get "/foo/write_raw_session" + get "/foo/read_session" + assert_equal "1", last_response.body - get "/foo/read_signed_cookie" - assert_equal "2", last_response.body + get "/foo/write_session" + get "/foo/read_session" + assert_equal "2", last_response.body - verifier = ActiveSupport::MessageVerifier.new(app.secrets.secret_token) + get "/foo/read_signed_cookie" + assert_equal "2", last_response.body - get "/foo/read_raw_cookie" - assert_equal 2, verifier.verify(last_response.body)["foo"] + verifier = ActiveSupport::MessageVerifier.new(app.secrets.secret_token) + + get "/foo/read_raw_cookie" + assert_equal 2, verifier.verify(last_response.body)["foo"] + ensure + ENV["RAILS_ENV"] = old_rails_env + end end test "calling reset_session on request does not trigger an error for API apps" do |