Rails/Heroku/Cloudflare: Can't verify CSRF token authenticity after domain change - ruby-on-rails

We have a Rails 5.2.3 app in production using Devise 4.6.2 and being deployed at Heroku. The app was using a domain example.com and everything was fine. Today we needed to change that domain to app.example.com (example.com is now a WordPress site) and now when we try to log into the app we're getting:
Can't verify CSRF token authenticity
Completed 422 Unprocessable Entity in 19ms
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/request_forgery_protection.rb:211:in `handle_unverified_request'
One thing I've realized is that now our production app isn't setting the session cookie. Our staging app (which uses an example.herokuapp.com domain) sets a cookie named '_myapp_session' (and it's still working fine), while in our production app there's no cookie being set.
While googling about this I've found some mentions to the session_store.rb config (we didn't even had this file), so I created the file in config/initializers and tried to set to our app.example.com domain and also to domain: :all, but it didn't seem to make any difference.
Rails.application.config.session_store :cookie_store, key: '_app_myapp_session', domain: :all
What I am missing here? Why would the domain change stop the app from creating the session cookie?
Oh, and we're using Cloudflare as our DNS and its __cfduid cookie is being correctly set. Could that be related?

So, apparently it was indeed related to Cloudflare. Our app.example.com entry on Cloudflare's DNS was "proxied" and once I've set it to "DNS only" and waited a few minutes our session cookies started appearing again.
I've just now realized that Cloudflare has its own cache, so I've purged that and will try to use the "proxied" setting again, but if that doesn't work I'll just use it as DNS.
If someone has details on why Cloudflare's proxied setting would stop the cookies from being set, please let me know. Thanks!

Did you read this post about Cloudflare cached pages and CSRF?
Poor tl;dr: If you cache a page with a CSRF protected form you have to update de CSRF using Ajax.
https://blog.cloudflare.com/the-curious-case-of-caching-csrf-tokens/

Related

Rails 4 upgrade throwing InvalidAuthenticityToken

My application just upgraded to Rails 4 and we're starting to see random InvalidAuthenticityToken errors. I have done a bunch of investigating but not yet found a solution. Anyone know what happened and how to fix it?
Calling out things that appeared in other similar SO questions but do not apply to me:
We call protect_from_forgery with: :exception in ApplicationController, but we were doing this in Rails 3 as well and did not have this error.
I have confirmed these are normal users using the website in a standard fashion; these are not CSRF attempts.
These are not API calls, they are standard web form submissions.
The authenticity token is present in both the form (via Rails form_for or form_tag generation) and in the submitted request.
My sessions should not have an expiration set, since I do not set an expiration time and the Rails default is forever, and my users don't often log in or out (so expired tokens are unlikely, as is "had a tab open, logged into a separate tab, went back to open tag and attempted action").
The csrf_meta_tag was generating the same tokens as my forms and removing it does not help.
My users confirmed they experienced this on at minimum Firefox, Chrome and Safari.
All code is available on Github.
Possibly relatedly: if I change my development secret_key_base in secrets.yml and change my session_store.rb file to use:
Rails.application.config.session_store :cookie_store, key: '_glowfic_constellation_' + Rails.env, domain: 'glowfic.com', tld_length: 2 and restart the server, I am logged out and can reliably experience this error 100% of the time when attempting to log in.
Edit calling out a couple more things:
I can't force clear all sessions because I use cookie stores, but I've already reset the secret_key_base and cookie name in production, which (hard to tell but I think) helped? But did not fix the issue.
The "possibly related" seems to be unrelated, and to have been related to the domain "glowfic.com" not supporting "localhost"; if I use the domain localhost instead, I can't reproduce locally.

Session cookie not being created only in production

I've been struggling with this for a while now and just can’t figure out why this is not working. I use Firefox/Firebug to see the session cookie being created in Development mode but when I run locally in Production the session cookie is not created. This, of course, causes all sorts of grief when the CSRF token is not in the session cookie and an exception is thrown.
The obvious place to look is in production.rb vs development.rb as all the rest of the code is the same however I can't see anything wrong there and I compared both files to a (test) newly created rails app.
Config Info:
session_store => cookie_store (rails default)
protect_from_forgery with: :exception (application_controller)
Any thoughts are appreciated. Thanks, Art
When I recently encountered the same situation, it turned out to be a problem with misconfigured session cookie domain.
Look into the HTTP headers your application sends with the responses. I guess the Set-Cookie header is sent for the session cookie as expected, but the browser refuses to save the cookie, because domain specified in the header doesn't match the actual production domain your application is running on.
To fix this, fix domain setting in the session store configuration.
Nope, neither of these were the problem. It was using Rack::Cached. I didn't have time to track down the why of it, just that removing it from my build stopped the problem without having to do anything else. Wish I'd had time to track this down further to help you all out.

SSL Requests on staging environments fail

Our mobile app recently stopped authenticating properly with our server on our staging and staging2 environments. Fortunately production is fine.
We're using force_ssl in our API's Session and Registration controllers. It was working fine before; not really sure what changed.
What seems to be happening is that our app submits a POST request to either create a new session or user. This request is over SSL, but we get a 301 Moved Permanently with a location identical to the initial request. I believe this redirect is performed via GET and since no routes match a GET to that URL, we then get a 404 Not Found.
I can't figure out why this changed recently and why it's not affecting production.
Turns out it was something having to do with Engine Yard, and an upgrade of our environment solved the problem.

Strange Spree Login Issue - Possibly cookie, browser, NGINX related

We are currently having a very strange issue that is occurring with a Spree install running on NGINX. Users are reporting issues recovering passwords and once recovered having issues of logging into the site. We have not been able to reproduce this error but know it is certainly happening due to all of the reports from users we are receiving. Also to not is users are able to login when they try a different browser. If the first attempt is in Firefox and then they try Chrome chrome will end up working in a good amount of cases.
Email from user:
"Still not getting through to shop. I have changed my password twice now and when I got to put it in nothing happens. It just refreshes the page and I am left with a blank spot for e-mail and password. "
Errors in the NGINX error log:
cache: [GET /login] miss
cache: [POST /user/sign_in] invalidate, pass
Configuration:
Rails 3.1, Spree 1, passenger-3.0.11, ruby 1.8.7 REE
Any and all answers / suggestions are GREATLY appreciated.
Two rails applications were running on both a domain and a subdomain and the browser had conflicts with the session cookie set in the file session_store.rb that had the same key and would not allow users to login if they had the cookie from sample-domain.com first or shop.sample-domain.com respectively.

Rails Checkout SSL heroku

I have my app deployed with heroku and have a SSL configured to one of my subdomain(secure.mydomain.com). I would like only order part of my app to use this ssl so in my orders controller I have a before filter to redirect the request to my secure subdomain. However all the session information is lost when it is redirected. I think because of the subdomain. How do I redirect this so that session information (cart info which is stored in db and some id information) can be retrieved. Can some one help please.
THanks
KIran
In your config/intializers/session_store.rb change it to
Yourapp::Application.config.session_store :cookie_store, :key => '_yourapp_session', :domain=>:all
The secret-sauce is the domain... When set to all, cookies will be stored across all subdomains and the main domain.

Resources