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.
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:
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With