From 3a97747f2d91df0c0e43a4002f2adaad87aed602 Mon Sep 17 00:00:00 2001 From: Scott Gibson Date: Fri, 28 Aug 2020 17:08:24 -0400 Subject: [PATCH 01/13] allow single_access_token via http headers --- .../controller_adapters/abstract_adapter.rb | 4 ++ lib/authlogic/session/base.rb | 69 +++++++++++++++++++ lib/authlogic/test_case.rb | 6 ++ .../test_case/mock_api_controller.rb | 4 ++ lib/authlogic/test_case/mock_controller.rb | 4 ++ test/session_test/headers_test.rb | 61 ++++++++++++++++ test/test_helper.rb | 8 +++ 7 files changed, 156 insertions(+) create mode 100644 test/session_test/headers_test.rb diff --git a/lib/authlogic/controller_adapters/abstract_adapter.rb b/lib/authlogic/controller_adapters/abstract_adapter.rb index fff08e8b..16c8a3b3 100644 --- a/lib/authlogic/controller_adapters/abstract_adapter.rb +++ b/lib/authlogic/controller_adapters/abstract_adapter.rb @@ -37,6 +37,10 @@ def params controller.params end + def headers + controller.headers + end + def request controller.request end diff --git a/lib/authlogic/session/base.rb b/lib/authlogic/session/base.rb index 716b658a..607555b5 100644 --- a/lib/authlogic/session/base.rb +++ b/lib/authlogic/session/base.rb @@ -236,6 +236,19 @@ def initialize(session) # # You can modify all of this behavior with the Config sub module. # + # Headers + # ======= + # + # This module is responsible for authenticating the user via headers, which requires + # setting HTTP header, for example, the following curl command: + # + # curl -H "user_credentials: 4LiXF7FiGUppIPubBPey" https://www.domain.com + # + # Notice the token in the header parameter, this is a single access token. This headers + # method operates exactly as the params method. + # + # You can modify all of this behavior with the Config sub module. + # # Perishable Token # ================ # @@ -410,6 +423,7 @@ def self.#{method}(*filter_list, &block) # `persist` callbacks, in order of priority persist :persist_by_params + persist :persist_by_headers persist :persist_by_cookie persist :persist_by_session persist :persist_by_http_auth, if: :persist_by_http_auth? @@ -857,6 +871,24 @@ def params_key(value = nil) end alias params_key= params_key + # Works exactly like cookie_key, but for headers. So a user can login via + # headers just like a cookie or a session. Your URL would look like: + # + # curl -H "user_credentials: 4LiXF7FiGUppIPubBPey" https://www.domain.com + # + # You can change the "user_credentials" key above with this + # configuration option. Keep in mind, just like cookie_key, if you + # supply an id the id will be appended to the front. Check out + # cookie_key for more details. Also checkout the "Single Access / + # Private Feeds Access" section in the README. + # + # * Default: cookie_key + # * Accepts: String + def headers_key(value = nil) + rw_config(:headers_key, value, cookie_key) + end + alias headers_key= headers_key + # Works exactly like login_field, but for the password instead. Returns # :password if a login_field exists. # @@ -1900,6 +1932,34 @@ def params_key build_key(self.class.params_key) end + def headers_credentials + controller.headers[headers_key] + end + + def headers_enabled? + if !headers_credentials || !klass.column_names.include?("single_access_token") + return false + end + if controller.responds_to_single_access_allowed? + return controller.single_access_allowed? + end + headers_enabled_by_allowed_request_types? + end + + def headers_enabled_by_allowed_request_types? + case single_access_allowed_request_types + when Array + single_access_allowed_request_types.include?(controller.request_content_type) || + single_access_allowed_request_types.include?(:all) + else + %i[all any].include?(single_access_allowed_request_types) + end + end + + def headers_key + build_key(self.class.headers_key) + end + def password_field self.class.password_field end @@ -1927,6 +1987,15 @@ def persist_by_params self.single_access = valid? end + def persist_by_headers + return false unless headers_enabled? + self.unauthorized_record = search_for_record( + "find_by_single_access_token", + headers_credentials + ) + self.single_access = valid? + end + def persist_by_http_auth login_proc = http_auth_login_proc diff --git a/lib/authlogic/test_case.rb b/lib/authlogic/test_case.rb index 476f769e..81f7b907 100644 --- a/lib/authlogic/test_case.rb +++ b/lib/authlogic/test_case.rb @@ -195,6 +195,12 @@ class <<@request end end + if @request && !@request.respond_to?(:headers) + class <<@request + alias_method :headers, :parameters + end + end + Authlogic::Session::Base.controller = @request && Authlogic::TestCase::RailsRequestAdapter.new(@request) || controller diff --git a/lib/authlogic/test_case/mock_api_controller.rb b/lib/authlogic/test_case/mock_api_controller.rb index 3fe4e38e..852c50cb 100644 --- a/lib/authlogic/test_case/mock_api_controller.rb +++ b/lib/authlogic/test_case/mock_api_controller.rb @@ -26,6 +26,10 @@ def params @params ||= {} end + def headers + @headers ||= {} + end + def request @request ||= MockRequest.new(self) end diff --git a/lib/authlogic/test_case/mock_controller.rb b/lib/authlogic/test_case/mock_controller.rb index f1dcc1c4..5d51c9b3 100644 --- a/lib/authlogic/test_case/mock_controller.rb +++ b/lib/authlogic/test_case/mock_controller.rb @@ -38,6 +38,10 @@ def params @params ||= {} end + def headers + @headers ||= {} + end + def request @request ||= MockRequest.new(self) end diff --git a/test/session_test/headers_test.rb b/test/session_test/headers_test.rb new file mode 100644 index 00000000..ffe25fad --- /dev/null +++ b/test/session_test/headers_test.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +require "test_helper" + +module SessionTest + module HeadersTest + class ConfigTest < ActiveSupport::TestCase + def test_headers_key + UserSession.headers_key = "my_headers_key" + assert_equal "my_headers_key", UserSession.headers_key + + UserSession.headers_key "user_credentials" + assert_equal "user_credentials", UserSession.headers_key + end + + def test_single_access_allowed_request_types + UserSession.single_access_allowed_request_types = ["my request type"] + assert_equal ["my request type"], UserSession.single_access_allowed_request_types + UserSession.single_access_allowed_request_types( + ["application/rss+xml", "application/atom+xml"] + ) + assert_equal( + ["application/rss+xml", "application/atom+xml"], + UserSession.single_access_allowed_request_types + ) + end + end + + class InstanceMethodsTest < ActiveSupport::TestCase + def test_persist_persist_by_headers + ben = users(:ben) + session = UserSession.new + + refute session.persisting? + set_headers_for(ben) + + refute session.persisting? + refute session.unauthorized_record + refute session.record + assert_nil controller.session["user_credentials"] + + set_request_content_type("text/plain") + refute session.persisting? + refute session.unauthorized_record + assert_nil controller.session["user_credentials"] + + set_request_content_type("application/atom+xml") + assert session.persisting? + assert_equal ben, session.record + + # should not persist since this is single access + assert_nil controller.session["user_credentials"] + + set_request_content_type("application/rss+xml") + assert session.persisting? + assert_equal ben, session.unauthorized_record + assert_nil controller.session["user_credentials"] + end + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index f2e3de8c..029ff3b2 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -274,6 +274,14 @@ def unset_params controller.params["user_credentials"] = nil end + def set_headers_for(user) + controller.headers["user_credentials"] = user.single_access_token + end + + def unset_headers + controller.headers["user_credentials"] = nil + end + def set_request_content_type(type) controller.request_content_type = type end From c299042843bb5869627ae809796e23286f009930 Mon Sep 17 00:00:00 2001 From: Scott Gibson Date: Fri, 28 Aug 2020 17:21:14 -0400 Subject: [PATCH 02/13] remove unnecessary setup --- lib/authlogic/test_case.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/authlogic/test_case.rb b/lib/authlogic/test_case.rb index 81f7b907..476f769e 100644 --- a/lib/authlogic/test_case.rb +++ b/lib/authlogic/test_case.rb @@ -195,12 +195,6 @@ class <<@request end end - if @request && !@request.respond_to?(:headers) - class <<@request - alias_method :headers, :parameters - end - end - Authlogic::Session::Base.controller = @request && Authlogic::TestCase::RailsRequestAdapter.new(@request) || controller From 404fa2b254d1a1f7b66f2f56c8ce4b25aa92f62e Mon Sep 17 00:00:00 2001 From: Scott Gibson Date: Fri, 11 Sep 2020 09:34:50 -0400 Subject: [PATCH 03/13] DRY it up --- lib/authlogic/session/base.rb | 65 +++++++------------ test/session_test/headers_test.rb | 61 ----------------- ...ms_test.rb => single_access_token_test.rb} | 18 ++++- 3 files changed, 40 insertions(+), 104 deletions(-) delete mode 100644 test/session_test/headers_test.rb rename test/session_test/{params_test.rb => single_access_token_test.rb} (79%) diff --git a/lib/authlogic/session/base.rb b/lib/authlogic/session/base.rb index 607555b5..bdbb9572 100644 --- a/lib/authlogic/session/base.rb +++ b/lib/authlogic/session/base.rb @@ -1908,54 +1908,37 @@ def params_credentials controller.params[params_key] end - def params_enabled? - if !params_credentials || !klass.column_names.include?("single_access_token") - return false - end - if controller.responds_to_single_access_allowed? - return controller.single_access_allowed? - end - params_enabled_by_allowed_request_types? + def headers_credentials + controller.headers[headers_key] end - def params_enabled_by_allowed_request_types? - case single_access_allowed_request_types - when Array - single_access_allowed_request_types.include?(controller.request_content_type) || - single_access_allowed_request_types.include?(:all) - else - %i[all any].include?(single_access_allowed_request_types) - end + def params_enabled? + params_credentials && single_access_token_enabled? end - def params_key - build_key(self.class.params_key) + def headers_enabled? + headers_credentials && single_access_token_enabled? end - def headers_credentials - controller.headers[headers_key] - end + def single_access_token_enabled? + return false unless klass.column_names.include?("single_access_token") + return controller.single_access_allowed? if controller.responds_to_single_access_allowed? - def headers_enabled? - if !headers_credentials || !klass.column_names.include?("single_access_token") - return false - end - if controller.responds_to_single_access_allowed? - return controller.single_access_allowed? - end - headers_enabled_by_allowed_request_types? + single_access_token_allowed_by_request_type? end - def headers_enabled_by_allowed_request_types? - case single_access_allowed_request_types - when Array - single_access_allowed_request_types.include?(controller.request_content_type) || - single_access_allowed_request_types.include?(:all) + def single_access_token_allowed_by_request_type? + if single_access_allowed_request_types.is_a?(Array) + (single_access_allowed_request_types & [controller.request_content_type, :all]).any? else %i[all any].include?(single_access_allowed_request_types) end end + def params_key + build_key(self.class.params_key) + end + def headers_key build_key(self.class.headers_key) end @@ -1979,19 +1962,17 @@ def persist_by_cookie end def persist_by_params - return false unless params_enabled? - self.unauthorized_record = search_for_record( - "find_by_single_access_token", - params_credentials - ) - self.single_access = valid? + persist_by_single_access_token(params_credentials) if params_enabled? end def persist_by_headers - return false unless headers_enabled? + persist_by_single_access_token(headers_credentials) if headers_enabled? + end + + def persist_by_single_access_token(credentials) self.unauthorized_record = search_for_record( "find_by_single_access_token", - headers_credentials + credentials ) self.single_access = valid? end diff --git a/test/session_test/headers_test.rb b/test/session_test/headers_test.rb deleted file mode 100644 index ffe25fad..00000000 --- a/test/session_test/headers_test.rb +++ /dev/null @@ -1,61 +0,0 @@ -# frozen_string_literal: true - -require "test_helper" - -module SessionTest - module HeadersTest - class ConfigTest < ActiveSupport::TestCase - def test_headers_key - UserSession.headers_key = "my_headers_key" - assert_equal "my_headers_key", UserSession.headers_key - - UserSession.headers_key "user_credentials" - assert_equal "user_credentials", UserSession.headers_key - end - - def test_single_access_allowed_request_types - UserSession.single_access_allowed_request_types = ["my request type"] - assert_equal ["my request type"], UserSession.single_access_allowed_request_types - UserSession.single_access_allowed_request_types( - ["application/rss+xml", "application/atom+xml"] - ) - assert_equal( - ["application/rss+xml", "application/atom+xml"], - UserSession.single_access_allowed_request_types - ) - end - end - - class InstanceMethodsTest < ActiveSupport::TestCase - def test_persist_persist_by_headers - ben = users(:ben) - session = UserSession.new - - refute session.persisting? - set_headers_for(ben) - - refute session.persisting? - refute session.unauthorized_record - refute session.record - assert_nil controller.session["user_credentials"] - - set_request_content_type("text/plain") - refute session.persisting? - refute session.unauthorized_record - assert_nil controller.session["user_credentials"] - - set_request_content_type("application/atom+xml") - assert session.persisting? - assert_equal ben, session.record - - # should not persist since this is single access - assert_nil controller.session["user_credentials"] - - set_request_content_type("application/rss+xml") - assert session.persisting? - assert_equal ben, session.unauthorized_record - assert_nil controller.session["user_credentials"] - end - end - end -end diff --git a/test/session_test/params_test.rb b/test/session_test/single_access_token_test.rb similarity index 79% rename from test/session_test/params_test.rb rename to test/session_test/single_access_token_test.rb index 5d280f13..9109afd6 100644 --- a/test/session_test/params_test.rb +++ b/test/session_test/single_access_token_test.rb @@ -13,6 +13,14 @@ def test_params_key assert_equal "user_credentials", UserSession.params_key end + def test_headers_key + UserSession.headers_key = "my_headers_key" + assert_equal "my_headers_key", UserSession.headers_key + + UserSession.headers_key "user_credentials" + assert_equal "user_credentials", UserSession.headers_key + end + def test_single_access_allowed_request_types UserSession.single_access_allowed_request_types = ["my request type"] assert_equal ["my request type"], UserSession.single_access_allowed_request_types @@ -28,11 +36,19 @@ def test_single_access_allowed_request_types class InstanceMethodsTest < ActiveSupport::TestCase def test_persist_persist_by_params + persist_persist_by(:params) + end + + def test_persist_persist_by_headers + persist_persist_by(:headers) + end + + def persist_persist_by(headers_or_params) ben = users(:ben) session = UserSession.new refute session.persisting? - set_params_for(ben) + send("set_#{headers_or_params}_for", ben) refute session.persisting? refute session.unauthorized_record From 575f177c9c91f4639ffa9091a30f6ab3343ef6ea Mon Sep 17 00:00:00 2001 From: Scott Gibson Date: Fri, 11 Sep 2020 09:43:31 -0400 Subject: [PATCH 04/13] forgot to modify test module name --- test/session_test/single_access_token_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/session_test/single_access_token_test.rb b/test/session_test/single_access_token_test.rb index 9109afd6..1d761549 100644 --- a/test/session_test/single_access_token_test.rb +++ b/test/session_test/single_access_token_test.rb @@ -3,7 +3,7 @@ require "test_helper" module SessionTest - module ParamsTest + module SingleAccessTokenTest class ConfigTest < ActiveSupport::TestCase def test_params_key UserSession.params_key = "my_params_key" From ca042150569def52b3c0134277ecf4ba71b59287 Mon Sep 17 00:00:00 2001 From: Scott Gibson Date: Mon, 14 Sep 2020 18:45:15 -0400 Subject: [PATCH 05/13] Use suggested Set intersect instead of array `&` Co-authored-by: Jared Beck --- lib/authlogic/session/base.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/authlogic/session/base.rb b/lib/authlogic/session/base.rb index bdbb9572..980c248d 100644 --- a/lib/authlogic/session/base.rb +++ b/lib/authlogic/session/base.rb @@ -1929,7 +1929,9 @@ def single_access_token_enabled? def single_access_token_allowed_by_request_type? if single_access_allowed_request_types.is_a?(Array) - (single_access_allowed_request_types & [controller.request_content_type, :all]).any? + Set.new(single_access_allowed_request_types).intersect?( + Set[controller.request_content_type, :all] + ) else %i[all any].include?(single_access_allowed_request_types) end From f21b4ceb7f16326e73a535e9f4e55205a6ca2382 Mon Sep 17 00:00:00 2001 From: Scott Gibson Date: Mon, 14 Sep 2020 18:48:04 -0400 Subject: [PATCH 06/13] add changelog entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a720072c..4ef39d2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -97,6 +97,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added - [#684](https://github.com/binarylogic/authlogic/pull/684) - Use cookies only when available. Support for `ActionController::API` + - [#728](https://github.com/binarylogic/authlogic/pull/728) - Allow + single_access_token to be supplied using Headers in addition to Params. - Fixed - [#725](https://github.com/binarylogic/authlogic/pull/725) - `NoMethodError` when setting `sign_cookie` or `encrypt_cookie` before `controller` is From b50cedd236c6393fb15cdf4fd937b2f1c171ee40 Mon Sep 17 00:00:00 2001 From: Scott Gibson Date: Tue, 15 Sep 2020 08:31:31 -0400 Subject: [PATCH 07/13] punctuation Co-authored-by: Tieg Zaharia --- lib/authlogic/session/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/authlogic/session/base.rb b/lib/authlogic/session/base.rb index 980c248d..a18a596c 100644 --- a/lib/authlogic/session/base.rb +++ b/lib/authlogic/session/base.rb @@ -244,7 +244,7 @@ def initialize(session) # # curl -H "user_credentials: 4LiXF7FiGUppIPubBPey" https://www.domain.com # - # Notice the token in the header parameter, this is a single access token. This headers + # Notice the token in the header parameter, this is a single access token. This header's # method operates exactly as the params method. # # You can modify all of this behavior with the Config sub module. From d84b8c6e1c43b96e97064f3ca465e26d7c70dc2c Mon Sep 17 00:00:00 2001 From: Scott Gibson Date: Tue, 15 Sep 2020 08:32:46 -0400 Subject: [PATCH 08/13] test method naming clarity Co-authored-by: Tieg Zaharia --- test/session_test/single_access_token_test.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/session_test/single_access_token_test.rb b/test/session_test/single_access_token_test.rb index 1d761549..ccc9a6a3 100644 --- a/test/session_test/single_access_token_test.rb +++ b/test/session_test/single_access_token_test.rb @@ -36,14 +36,14 @@ def test_single_access_allowed_request_types class InstanceMethodsTest < ActiveSupport::TestCase def test_persist_persist_by_params - persist_persist_by(:params) + assert_persist_by(:params) end def test_persist_persist_by_headers - persist_persist_by(:headers) + assert_persist_by(:headers) end - - def persist_persist_by(headers_or_params) + + def assert_persist_by(headers_or_params) ben = users(:ben) session = UserSession.new From 24e7ab08306abe623e5505da08c3309ed0d77742 Mon Sep 17 00:00:00 2001 From: Scott Gibson Date: Tue, 15 Sep 2020 08:58:12 -0400 Subject: [PATCH 09/13] fix whitespace --- lib/authlogic/session/base.rb | 2 +- test/session_test/single_access_token_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/authlogic/session/base.rb b/lib/authlogic/session/base.rb index a18a596c..4b613766 100644 --- a/lib/authlogic/session/base.rb +++ b/lib/authlogic/session/base.rb @@ -885,7 +885,7 @@ def params_key(value = nil) # * Default: cookie_key # * Accepts: String def headers_key(value = nil) - rw_config(:headers_key, value, cookie_key) + rw_config(:headers_key, value) end alias headers_key= headers_key diff --git a/test/session_test/single_access_token_test.rb b/test/session_test/single_access_token_test.rb index ccc9a6a3..bee68c8d 100644 --- a/test/session_test/single_access_token_test.rb +++ b/test/session_test/single_access_token_test.rb @@ -42,7 +42,7 @@ def test_persist_persist_by_params def test_persist_persist_by_headers assert_persist_by(:headers) end - + def assert_persist_by(headers_or_params) ben = users(:ben) session = UserSession.new From ab04acdcd4eba8d7c5c338937593c14ff9cd16df Mon Sep 17 00:00:00 2001 From: Scott Gibson Date: Tue, 15 Sep 2020 14:51:17 -0400 Subject: [PATCH 10/13] Update lib/authlogic/session/base.rb Co-authored-by: Jared Beck --- lib/authlogic/session/base.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/authlogic/session/base.rb b/lib/authlogic/session/base.rb index 4b613766..17a2320b 100644 --- a/lib/authlogic/session/base.rb +++ b/lib/authlogic/session/base.rb @@ -249,6 +249,7 @@ def initialize(session) # # You can modify all of this behavior with the Config sub module. # + # Disabled by default. To enable, set a non-nil headers_key. # Perishable Token # ================ # From 03c2c4d56549a51a3843c38d50271cdd54f7596a Mon Sep 17 00:00:00 2001 From: Scott Gibson Date: Tue, 15 Sep 2020 14:53:22 -0400 Subject: [PATCH 11/13] default headers_key is nil --- lib/authlogic/session/base.rb | 2 +- test/session_test/single_access_token_test.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/authlogic/session/base.rb b/lib/authlogic/session/base.rb index 17a2320b..a8455092 100644 --- a/lib/authlogic/session/base.rb +++ b/lib/authlogic/session/base.rb @@ -883,7 +883,7 @@ def params_key(value = nil) # cookie_key for more details. Also checkout the "Single Access / # Private Feeds Access" section in the README. # - # * Default: cookie_key + # * Default: nil # * Accepts: String def headers_key(value = nil) rw_config(:headers_key, value) diff --git a/test/session_test/single_access_token_test.rb b/test/session_test/single_access_token_test.rb index bee68c8d..6a7843b5 100644 --- a/test/session_test/single_access_token_test.rb +++ b/test/session_test/single_access_token_test.rb @@ -6,6 +6,8 @@ module SessionTest module SingleAccessTokenTest class ConfigTest < ActiveSupport::TestCase def test_params_key + assert_equal UserSession.cookie_key, UserSession.params_key + UserSession.params_key = "my_params_key" assert_equal "my_params_key", UserSession.params_key @@ -14,6 +16,8 @@ def test_params_key end def test_headers_key + assert_equal nil, UserSession.headers_key + UserSession.headers_key = "my_headers_key" assert_equal "my_headers_key", UserSession.headers_key @@ -40,6 +44,8 @@ def test_persist_persist_by_params end def test_persist_persist_by_headers + # Since default headers_key is nil, set for the test. + UserSession.send("headers_key=", "user_credentials") assert_persist_by(:headers) end From de7ce4e6eb3a8466a3a7a715851193d69391eb1b Mon Sep 17 00:00:00 2001 From: Scott Gibson Date: Tue, 15 Sep 2020 14:54:26 -0400 Subject: [PATCH 12/13] Update lib/authlogic/session/base.rb Co-authored-by: Jared Beck --- lib/authlogic/session/base.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/authlogic/session/base.rb b/lib/authlogic/session/base.rb index a8455092..27a9e174 100644 --- a/lib/authlogic/session/base.rb +++ b/lib/authlogic/session/base.rb @@ -1910,6 +1910,9 @@ def params_credentials end def headers_credentials + # Setting headers_key to nil is the accepted way to disable + # single_access_token in headers. + return nil if headers_key.nil? controller.headers[headers_key] end From 4c016ec6a480638dbc5cd38a8f652bfe1dcb4cee Mon Sep 17 00:00:00 2001 From: Scott Gibson Date: Fri, 6 Mar 2026 14:54:14 -0500 Subject: [PATCH 13/13] Use request.headers instead of response headers for single_access_token - Access controller.request.headers instead of controller.headers, which returns response headers - Transform headers_key to CGI-compliant format (HTTP_ prefix, uppercased, hyphens to underscores) to match Rack convention - Move headers hash from MockController to MockRequest - Remove unnecessary headers delegate from AbstractAdapter Co-Authored-By: Claude Opus 4.6 --- lib/authlogic/controller_adapters/abstract_adapter.rb | 4 ---- lib/authlogic/session/base.rb | 10 ++++++++-- lib/authlogic/test_case/mock_controller.rb | 4 ---- lib/authlogic/test_case/mock_request.rb | 4 ++++ test/test_helper.rb | 4 ++-- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/lib/authlogic/controller_adapters/abstract_adapter.rb b/lib/authlogic/controller_adapters/abstract_adapter.rb index 16c8a3b3..fff08e8b 100644 --- a/lib/authlogic/controller_adapters/abstract_adapter.rb +++ b/lib/authlogic/controller_adapters/abstract_adapter.rb @@ -37,10 +37,6 @@ def params controller.params end - def headers - controller.headers - end - def request controller.request end diff --git a/lib/authlogic/session/base.rb b/lib/authlogic/session/base.rb index 27a9e174..2ba59f86 100644 --- a/lib/authlogic/session/base.rb +++ b/lib/authlogic/session/base.rb @@ -1913,7 +1913,7 @@ def headers_credentials # Setting headers_key to nil is the accepted way to disable # single_access_token in headers. return nil if headers_key.nil? - controller.headers[headers_key] + controller.request.headers[headers_key] end def params_enabled? @@ -1946,7 +1946,13 @@ def params_key end def headers_key - build_key(self.class.headers_key) + # Rack servers uppercase header names, convert hyphens to underscores, + # and prefix with "HTTP_" to comply with CGI. We transform the key in + # the same way Rails does: + # https://github.com/rails/rails/blob/6-0-stable/actionpack/lib/action_dispatch/http/headers.rb#L123-L126 + key = build_key(self.class.headers_key) + return nil if key.nil? + "HTTP_" + key.upcase.tr("-", "_") end def password_field diff --git a/lib/authlogic/test_case/mock_controller.rb b/lib/authlogic/test_case/mock_controller.rb index 5d51c9b3..f1dcc1c4 100644 --- a/lib/authlogic/test_case/mock_controller.rb +++ b/lib/authlogic/test_case/mock_controller.rb @@ -38,10 +38,6 @@ def params @params ||= {} end - def headers - @headers ||= {} - end - def request @request ||= MockRequest.new(self) end diff --git a/lib/authlogic/test_case/mock_request.rb b/lib/authlogic/test_case/mock_request.rb index 6848d17f..1d8b6b14 100644 --- a/lib/authlogic/test_case/mock_request.rb +++ b/lib/authlogic/test_case/mock_request.rb @@ -19,6 +19,10 @@ def format controller.request_content_type if controller.respond_to? :request_content_type end + def headers + @headers ||= {} + end + def ip controller&.respond_to?(:env) && controller.env.is_a?(Hash) && diff --git a/test/test_helper.rb b/test/test_helper.rb index 029ff3b2..d55d36c2 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -275,11 +275,11 @@ def unset_params end def set_headers_for(user) - controller.headers["user_credentials"] = user.single_access_token + controller.request.headers["HTTP_USER_CREDENTIALS"] = user.single_access_token end def unset_headers - controller.headers["user_credentials"] = nil + controller.request.headers["HTTP_USER_CREDENTIALS"] = nil end def set_request_content_type(type)