Rails 6 - InvalidAuthenticityToken on Heroku - ruby-on-rails

I've seen no answers on SO so far that don't answer this without suggesting to just disable it (which I don't want to do).
Locally, everything works, but deployed to producton on Heroku I'm getting InvalidAuthenticityToken.
From everything I can see, everything is set up properly.
Fresh app on Rails 6.0.3.1 (so it's not migrated where the setting may be disabled by default)
RAILS_MASTER_KEY set in Heroku for session
session_store.rb set to Rails.application.config.session_store :cookie_store, key: '__app_session', expire_after: 1.year
csrf_meta_tags in my layout as well as csp_meta_tag
ajax not used, this is a plain form_with. I can see the CSRF tag in dev tools so I know it's in the HTML
I considered it maybe is because of this in ApplicationController:
before_action :authenticate
however it seems that prepend: true is no longer set within the application controller...
I tried overriding it anyway by just adding it (even though it's not there by default and it still doesnt work if I add this above the before_action line)
protect_from_forgery with: :exception, prepend: true
Edit I'll also say the fixed Sidekiq showing forbidden when trying to issue DELETE commands as well (kill job button)

Try adding config.force_ssl = true in your config/environments/production.rb and make sure your SSL is configured properly like you said switching to Full SSL instead of Flexible.

Related

How can I set cookies in a browser from a Rails API app hosted in Heroku running the frontend in a React app hosted in Netlify?

I built an API with Rails --api --db:postgres flags. I built the frontend in another app using React create app.
Rails 6.1.4.1, Ruby 3.0.2p107
The Rails app is deployed in Heroku
The React app, in Netlify
I'm using session cookies to store the user id, and the CSRF Token for additional security (mainly for learning purposes)
Both cookies are set properly and as expected in my local environment, by running the rails server in port localhost:3001 and react in port localhost:3000.
However, after deploying Rails in herokuapp.com and React in netlify.app, although the browser receives the cookies in the response, it doesn't set them.
This is what I see in the browser:
Cookies Response
My Cors.rb file is set properly to allow my the netlify domain to connect to the server, like so my-domain.netlify.app and https://my-domain.netlify.app.
When setting the cookies I have tried every imaginable possible combination of settings, but nothing seems to work. At the moment it looks something like this:
def set_csrf_cookie
cookies['CSRF-TOKEN'] = {
value: form_authenticity_token,
domain: my-app.herokuapp.com,
same_site: :None,
secure: true
}
end
In my cors.rb file I have this code on the first line:
Rails.application.config.action_controller.forgery_protection_origin_check = false
My application.rb file has this config:
config.api_only = true
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore
My application controller looks something like this:
class ApplicationController < ActionController::API
before_action :set_csrf_cookie
include ActionController::Cookies
include ActionController::RequestForgeryProtection
protect_from_forgery with: :exception
include Response
include ExceptionHandler
def cookie
'ok'
end
private
def set_csrf_cookie
cookies['CSRF-TOKEN'] = {
value: form_authenticity_token,
domain: 'my-app.herokuapp.com',
same_site: :None,
secure: true
}
end
end
I set the cookies by making an API call from my App.js component. The call is made to the path '/', which is routed to application#cookie, which you can see in the application controller code above.
I know I am able to connect with the API because some endpoints that don't require the CSRF Token, are working properly.
I have a feeling that my issue has something to do with the app being hosted in 2 different domains. I also think that it might be a front-end issue, not a back-end issue.
Help from anyone who has successfully done this would be most appreciated.
After much research and a lot of tests, I discovered that the main reason why my cookies were not working is because of the way browsers handle third-party cookies nowadays.
It turns out that Safari and Chrome block them by default. I also missed the fact that cross-site cookies don't actually exist.
I wrote an article explaining how I solved the issue: https://medium.com/#ArturoAlvarezV/use-session-cookies-to-authenticate-a-user-with-a-rails-api-backend-hosted-in-heroku-on-one-domain-f702ddf8c07
Basically, my solution was very simple, remove cross-site-tracking protection from the browsers, using Ruby on Rails gem called 'rails_same_site_cookie', and add this line to my production.rb file:
config.action_dispatch.cookies_same_site_protection = :None
This did the trick for me. This line turned all cookies in rails to SameSite:None and Secure:true by default, including Rail's built-in session cookie.
My developer tools don't show the cookies in my cookies panel, but now they are set and sent with my credentials every time I make a request to the API.

ActionController::InvalidAuthenticityToken coming suddenly

I have old project in Rails 5, I have to add Api and it was working fine, 3 days ago, but now it suddenly started to give me ActionController::InvalidAuthenticityToken I have done no changes in any controller related to web, but added few Gems includes rspec-rails, jwt and creating its Api, but suddenly on chrome it is giving me this error.
When I started work I tested and it was working fine, and on Safari browser it works fine. But on Chrome it gives this error. Following line is added in my application, if I disable this error goes, but I think that will make it unsecure.
protect_from_forgery with: :exception, prepend: true
I check few answers where long list that it s old issue, but I am working on many rails project and I never saw this issue! Some post direct me to use https so I also used https but issue for chrome is still there.
Any help
I originally had only a me-too comment.
But with sheer luck, I happen to know the answer.
It is not your code that changes; it's the browsers.
Please check the news related to Same-Site policy changes from Google.
Basically, the cookie is not working in your environment anymore because of changes in the browser, rendering the CSRF token unusable.
You have to config Rails.application.config.session_store in an initializer; unfortunately, there is no one-liner fixed all in this situation; it depends on the environment and situations.
Just put the below the line in your ApplicationController
skip_before_action :verify_authenticity_token

ActionController::InvalidAuthenticityToken Rails 5 / Devise / Audited / PaperTrail gem

Background Details
I am using Devise for authentication to login to a Rails 5 application.
Whenever I bundle either the Audited or Paper Trail gem, when I attempt to #create a new session (via the sign in form - /users/sign_in), I receive the following error:
ActionController::InvalidAuthenticityToken
Environment Details
Ruby 2.3.1
Gems:
rails 5.0.2
devise => 4.2.1
paper_trail => 7.0.1
Steps to Reproduce:
Create Rails 5 application
Add Devise gem
Add Audited or Paper Trail gem
Attempt to login
As it turns out, Devise documentation is quite revealing with regard to this error:
For Rails 5, note that protect_from_forgery is no longer prepended to
the before_action chain, so if you have set authenticate_user before
protect_from_forgery, your request will result in "Can't verify CSRF
token authenticity." To resolve this, either change the order in which
you call them, or use protect_from_forgery prepend: true.
The fix was to change code in my application controller from this:
protect_from_forgery with: :exception
To this:
protect_from_forgery prepend: true
This issue did not manifest itself until I attempted adding Audited or Paper Trail gems.
This happened to me on my development machine. Turns out I was setting
Rails.application.config.session_store
for security purpose in production. And somehow in this code gets run on development mode. And I have to comment out this line and it works fine now.
Rails.application.config.session_store :cookie_store, key: '_my_session', secure: true, same_site: :strict
Another thing to try for anyone running into this is to add the following to your environment configuration file:
config.action_controller.forgery_protection_origin_check = false
For me, production was working correctly but staging and development were not and this fixed it for me.
In my project we have that problem and we can't to override protect_from_forgery.
The solution founded is indicate the github of audited and worked for me.
Put this in gemfile:
gem "audited", github: "collectiveidea/audited"
As mentioned in the documentation.
For Rails 5, note that protect_from_forgery is no longer prepended
to the before_action chain, so if you have set authenticate_user
before protect_from_forgery, your request will result in "Can't verify
CSRF token authenticity." To resolve this, either change the order in
which you call them, or use protect_from_forgery prepend: true.
I have used something like this and it works for me.
class WelcomeController < ::Base
protect_from_forgery with: :exception
before_action :authenticate_model!
end
The solution for me was to manually go to my browser's settings and delete the cache.

Rails app using force_ssl on entire site when it shouldn't

Something has changed in my environment and I don't know why. I use SSL only for logging in through my sessions controller, which was working.
force_ssl :only => [:signin] unless Rails.env.development?
After logging in, a user is redirected to the home page, which should not be HTTPS. Now everything is be forced to SSL. In my production.rb file I set force_ssl to false, which it should be by default but that didn't resolve the problem.
I've also tried the solution posted here about using a protocol restraint in routes.rb which didn't work either.
Rails force ssl only on specified controllers
I've restarted nginx and unicorn several times but still forcing SSL. SSL is causing leafjs (map) not to work when my app tries to access its stylesheet and javascript from a remote location.
I could download them into my app but that wouldn't solve the forced_ssl problem.
My app is running on a DigitalOcean droplet, if that makes any difference.

Login authentication with Ember-cli, Rails and ember-cli-simple-auth-token

I have created an ember-cli project (v 0.1.12) with ember.js (v 1.8.1) and Rails. Than I tried to install:
https://www.npmjs.com/package/ember-cli-simple-auth-token
but when I run the login POST the server responds to me with this error:
Can't verify CSRF token authenticity.
I notice that it sends only username and password, without token. What's going on here?
The short answer is that you can fix that issue in the development setting by disabling CSRF tokens all together. You wouldn't use that in production but you can at least disable it to confirm that the issue gets fixed. In the application_controller.rb file, remove: protect_from_forgery line. Also go to your session_store.rb file in initializers and set:
# Be sure to restart your server when you modify this file.
Rails.application.config.session_store :disabled
Once you get things working, you can re-add the protect_from_forgery line as so:
protect_from_forgery with: :null_session

Resources