devise icon indicating copy to clipboard operation
devise copied to clipboard

Devise::FailureApp is not compatible with Rails 7.1 csrf_token_storage

Open mpvosseller opened this issue 1 year ago • 1 comments

Environment

  • Ruby 3.2.2
  • Rails 7.1+
  • Devise 4.9.4

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:

  • Implement a controller that 1) generates a CSRF token by calling for example form_authenticity_token and 2) calls :authenticate_user!
  • Make an unauthenticated request to that controller
  • Observe that no session cookie is returned, no session is created, and the CSRF token is not stored

Expected behavior

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

  • Implement a controller that 1) generates a CSRF token by calling for example form_authenticity_token and 2) calls :authenticate_user!
  • Make an unauthenticated request to that controller
  • A session cookie should be returned and the CSRF token should be stored in the session

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.

mpvosseller avatar Jul 01 '24 13:07 mpvosseller

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

dmatamoroscr avatar Jul 12 '24 17:07 dmatamoroscr