diff --git a/lib/devise/hooks/csrf_cleaner.rb b/lib/devise/hooks/csrf_cleaner.rb index d725fbc4..211bcab8 100644 --- a/lib/devise/hooks/csrf_cleaner.rb +++ b/lib/devise/hooks/csrf_cleaner.rb @@ -4,6 +4,12 @@ Warden::Manager.after_authentication do |record, warden, options| clean_up_for_winning_strategy = !warden.winning_strategy.respond_to?(:clean_up_csrf?) || warden.winning_strategy.clean_up_csrf? if Devise.clean_up_csrf_token_on_authentication && clean_up_for_winning_strategy - warden.request.session.try(:delete, :_csrf_token) + request = warden.request + if request.respond_to?(:controller_instance) && request.controller_instance.respond_to?(:reset_csrf_token) + # Rails 7.1+ + request.controller_instance.reset_csrf_token(request) + else + request.session.try(:delete, :_csrf_token) + end end end diff --git a/test/integration/authenticatable_test.rb b/test/integration/authenticatable_test.rb index a1bf28da..6c3be3b5 100644 --- a/test/integration/authenticatable_test.rb +++ b/test/integration/authenticatable_test.rb @@ -346,10 +346,18 @@ class AuthenticationSessionTest < Devise::IntegrationTest test 'refreshes _csrf_token' do swap ApplicationController, allow_forgery_protection: true do get new_user_session_path - token = request.session[:_csrf_token] + token_from_session = request.session[:_csrf_token] + + if Devise::Test.rails71_and_up? + token_from_env = request.env["action_controller.csrf_token"] + end sign_in_as_user - assert_not_equal request.session[:_csrf_token], token + assert_not_equal request.session[:_csrf_token], token_from_session + + if Devise::Test.rails71_and_up? + assert_not_equal request.env["action_controller.csrf_token"], token_from_env + end end end