Problem loading Rails configuration

After upgrading our application to Rails 5.2, InvalidAuthenticityToken errors are found in our public APIs. The error is caused by CSRF protection is enabled by default since Rails 5.2 while it is not required in public APIs. I updated the config to disable the default behavior, but it doesn’t take effect.

# config/initializers/new_framework_defaults_5_2.rb
Rails.application.config.action_controller.default_protect_from_forgery = false

The problem

According to the source code, the config is used to toggle CSRF protection after ActionController::Base is loaded:

initializer "action_controller.request_forgery_protection" do |app|
  ActiveSupport.on_load(:action_controller_base) do
    puts "default_protect_from_forgery: #{app.config.action_controller.default_protect_from_forgery}"

    if app.config.action_controller.default_protect_from_forgery
      protect_from_forgery with: :exception
    end
  end
end

I use this gist to debug how configurations are loaded:

before_configuration
application.rb loaded
before_initialize
default_protect_from_forgery is true, expected: false
config/initializers loaded
ActiveSupport.on_load(:before_initialize) runs at the end of before_initialize
after_initialize
default_protect_from_forgery is false, expected: false
ActiveSupport.on_load(:after_initialize) runs at the end of after_initialize

The highlighted line shows the value of default_protect_from_forgery is true while it should be false. So the problem is ActionController::Base is loaded before loading config/initializers.

Investigation

I commented all gems except the rails gem, then uncommented them one by one and debug configuration loading with rails c to see the prints like above, finally found it is caused by the wechat gem:

Solution

The problem can be fixed if:

I created a repo for showing the problem, see the following commits for details: