heartcombo / devise

Flexible authentication solution for Rails with Warden.
http://blog.plataformatec.com.br/tag/devise/
MIT License
24.01k stars 5.55k forks source link

Devise::FailureApp is not compatible with Rails 7.1 csrf_token_storage #5698

Open mpvosseller opened 4 months ago

mpvosseller commented 4 months ago

Environment

Overview

Rails 7.1 changed how csrf token storage works and appears to break in Devise under some situations.

For proper behavior Rails now seems to expect controllers to include the commit_csrf_token method from ActionController::RequestForgeryProtection which is mixed into ActionController::Base and so is automatically available to most controllers. Devise::FailureApp however extends ActionController::Metal (not ActionController::Base) so it does not include this method.

Current behavior

Using Rails 7.1 (or higher) and redis_store for session storage:

Expected behavior

Using Rails 7.1 (or higher) and redis_store for session storage:

The problem is that at this line the controller_instance is a Devise::FailureApp which does not respond_to commit_csrf_token. Because of this the CSRF token is not written to the session, the session is not created / initialized, and no session cookie is returned.

Workaround

My current workaround is to include ActionController::RequestForgeryProtection in Devise::FailureApp which appears to fix it but I'm not sure if this could cause any problems or if there are additional cases that would need to be addressed.

module Devise
  class FailureApp
    include ActionController::RequestForgeryProtection
  end
end

I'm really not sure if this should be considered a Rails issue or a Devise issue but I filed a ticket with Rails to make them aware too.

dmatamoroscr commented 4 months ago

Might the Responder also need it? https://github.com/heartcombo/devise/blob/a259ff3c28912a27329727f4a3c2623d3f5cb6f2/lib/devise/controllers/responder.rb#L7