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

ActionController::InvalidAuthenticityToken #632

Open
lazaronixon opened this issue Jul 12, 2024 · 3 comments
Open

ActionController::InvalidAuthenticityToken #632

lazaronixon opened this issue Jul 12, 2024 · 3 comments
Labels
bug Something isn't working

Comments

@lazaronixon
Copy link

lazaronixon commented Jul 12, 2024

Describe the bug

When I try to submit to a main application controller, I receive ActionController::InvalidAuthenticityToken. For some reason, the session cookie is not created when I access /lookbook, but as soon as I open the main application and the session cookie is set, the following requests work without any problem.

To Reproduce

Rails.application.routes.draw do
  mount Lookbook::Engine, at: "/lookbook"
  resource :slow_action, only: :create
end
class SlowActionsController < ApplicationController
  # skip_forgery_protection

  def create
    sleep 3.seconds; head :created
  end
end

test/components/previews/button_preview/loading.html.erb

<%= form_with(url: main_app.slow_action_path) do |form| %>
  <%= form.button tag.span("Click and wait"), class: "btn btn--loading" %>
<% end %>
@lazaronixon lazaronixon added the bug Something isn't working label Jul 12, 2024
@allmarkedup
Copy link
Collaborator

allmarkedup commented Oct 9, 2024

Hey @lazaronixon, sorry for the super slow reply and thanks for the bug report.

I've just opened a PR that should fix this. I realise it's quite a while since you created this issue but if you are able to to test it and confirm it works for you too then that would be fantastic:

gem "lookbook", github: "lookbook-hq/lookbook", branch: "fix-preview-csrf-exception"

From my testing it seems to fix the issue so if I don't hear back with any problems I'll merge it in and get it out in the next release. Thanks again for bringing it to my attention :)

@halo
Copy link

halo commented Oct 10, 2024

Thank you for attempting to fix this issue. I'm a bit confused, though.

This is what my lookbook HTML looks like with a form_for tag:

<!-- http://127.0.0.1:3005/lookbook/inspect/toggle/async -->
<html>

<head>
  <!-- Your PR adds this one -->
  <meta name="csrf-token" content="3JWhDXzu1713DX..." /> 
</head>

<body>
  <!-- I don't think I can programmatically escape this iframe, right? I can't see the token above. -->
  <iframe>
    <html>

    <head>
      <title>Preview</title>
      <!-- This is from my Rails layout -->
      <meta name="csrf-token" content="iAhD6iIsCjEhorYn...">  
    </head>

    <body>
      <form id="..." action="..." accept-charset="UTF-8" method="post">
        <!-- This is what `form_for` adds -->
        <input type="hidden" name="authenticity_token" value="ReJTSC8SlGyDbfWo..." autocomplete="off">
      </form>
    </body>

    </html>
  </iframe>
</body>

</html>

What's being submitted is the token ReJTSC8SlGyDbfWo.... And because my session is not initialized yet, it will lead to a ActionController::InvalidAuthenticityToken.

However, if I add session[:test] = 'something' to the controller that takes the request (and reload the page), I have a session that matches the access token being submitted and I don't get the exception.

Your PR does not change this behavior.

My guess is that the underlying problem is the <iframe> that prevents the session from being set automatically. I don't think this is related to the meta tag in the lookbook layout at all.

See also https://discuss.rubyonrails.org/t/cant-verify-csrf-token-authenticity-in-iframe/85518 (but that is only addressing cross-domain issues I think)

See also https://security.stackexchange.com/questions/238443/iframe-friendly-csrf-protection

@allmarkedup
Copy link
Collaborator

Hey @halo, thanks for the reply. I'm a little stumped myself here I have to say because in my testing the changes in the PR do seem to fix the issue, at least with the test setup I've got.

I tried to recreate the scenario you describe using your example code in the Lookbook demo app - you can see the change here: lookbook-hq/lookbook-demo@b6b3795

Using the latest Lookbook version in this setup I see the same invalid token error as you describe. Using the PR branch the issue is resolved for me. I've done a little screencast to demonstrate clearing the cookies and refreshing the Lookbook preview view and you can see that (unlike before the change) the Rails session cookie is being set as part of the request. Submitting the form then works correctly:

CleanShot.2024-10-23.at.20.14.40.mp4

It may be that I've got the wrong end of the stick here in how I'm attempting to test it so please let me know if this is not what you actually mean! :)

FWIW you are right in saying that the CSRF meta tag outside of the preview iframe is no actual use to the document within the iframe itself. However, it is inserted into the Lookbook layout using the csrf_meta_tags helper which (as I understand it) triggers the application session cookie to be set, so it should then be already available when the preview is rendered.

However as this change has not fixed the issue for you I suspect there is some difference in setup/configuration between the (quite simplistic!) demo app and your application. A couple of questions that might help me figure out what that is:

  1. Are you using a custom preview controller? If so what does that class inherit from?
  2. Are you using a custom preview layout or do the components just render in your default application layout?
  3. Is there anything in the way I've tried to replicate your setup in the demo app that is obviously different from your setup?

In the meantime I'll try to have a think if there is any other reason why I might not be able to replicate the issue you are seeing even with the 'fix' in place.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants