Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
mpvosseller opened this issue Jul 1, 2024 · 1 comment

Comments

@mpvosseller
Copy link

mpvosseller commented Jul 1, 2024

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.

@dmatamoroscr
Copy link

Might the Responder also need it?

class Responder < ActionController::Responder

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants