Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

csrf_meta_tags and form_for generate invalid base64 on Heroku

I am using ruby 2.7.1 and rails 6.0.3.4 and hitting the following error whenever I try to call csrf_meta_tags or form_for

2021-02-01T07:25:10.058892+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab] ActionView::Template::Error (invalid base64):
2021-02-01T07:25:10.058893+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab]     1: <h2>Log in</h2>
2021-02-01T07:25:10.058894+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab]     2:
2021-02-01T07:25:10.058895+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab]     3: <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
2021-02-01T07:25:10.058895+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab]     4:   <div class="field">
2021-02-01T07:25:10.058896+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab]     5:     <%= f.label :email %><br />
2021-02-01T07:25:10.058898+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab]     6:     <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
2021-02-01T07:25:10.058899+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab]
2021-02-01T07:25:10.058899+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab] app/views/devise/sessions/new.html.erb:3

I only get this error in production when deployed to Heroku. In development, the authenticity token is generated without error, but for some reason on Heroku the above error ie produced. Any idea what could be going on here?

I have tried to narrow down what line(s) are causing the issue, and I got as far as form_authenticity_token and masked_authenticity_token but I so far have not been able to trace which lines are the issue.

Some other possibly relevant versions:

Gemfile.lock
------------
webpacker (4.3.0)

yarn.lock
---------
@rails/[email protected]

I've tried simply omitting the csrf_meta_tags but then I still hit the error on forms as shown above. I can't find any references to others with the same issue, so any help is greatly appreciated.

like image 785
cecomp64 Avatar asked Feb 01 '21 07:02

cecomp64


2 Answers

On our servers this problem was caused by downgrading Rails from 6.1 to 6.0.3.

Firstly we tried to upgrade rails from 6.0.3 to 6.1, but missed some needed changes for migration to be successful and had to revert back to 6.0.3. However, during the time our app ran on Rails 6.1 many user requests were served and new csrf tokens were generated. The thing is, Rails 6.1 has different algorithm for csrf token generation and when we reverted back to Rails 6.0.3, tokens that were generated by Rails 6.1 could not be validated.

To alleviate the problem and avoid showing errors to users we decorated csrf generation function to catch aforementioned errors and reset session so that tokens compatible with Rails 6.0.3 can be generated.

def rescued_csrf_meta_tags
  csrf_meta_tags
rescue ArgumentError
  request.reset_session
  csrf_meta_tags
end

Additional server info:

  • Ubuntu 16.04
  • Ruby 2.6.5

EDIT: As @cecomp64 wrote in the comment, another solution is to clear browser cache. Obviously, this won't be easy to implement if your app has many users.

like image 81
AurimasLazdauskas Avatar answered Nov 15 '22 08:11

AurimasLazdauskas


This is because the csrf token generation between Rails 5 and 6 is incompatible (different algorithm) and as such, you need a function to generate a new encryption to handle the aforementioned compatibility errors.

Your application_controller.rb:

protect_from_forgery with: :exception

Your application.html.erb in the head tag:

<%= csrf_meta_tags %>

Your application_helper.rb or csrf_helper.rb:

def csrf_meta_tags
  if defined?(protect_against_forgery?) && protect_against_forgery?
    [
      tag("meta", name: "csrf-param", content: request_forgery_protection_token),
      tag("meta", name: "csrf-token", content: form_authenticity_token)
    ].join("\n").html_safe
  end
end
like image 33
Talita Avatar answered Nov 15 '22 09:11

Talita