Tuesday, 18 May 2021

Rails ActionController::InvalidCrossOriginRequest on a js request

I know this has been brought up a few times on SO but I cannot make inroads. I'm on Rails 5.0.7.2.

I am getting ActionController::InvalidCrossOriginRequest thrown hundreds of times per day. Rollbar says it is mostly caused by Bingbot, and it's on my user signup modal, which is from Devise. It's a GET request, and the path is /users/sign_up.

NOTE: It's not a form. It's a modal that simply asks the user How would you like to sign up? Email, Fb, Google auth, etc.

Basically I have some javascript actions on my site, picture like a reddit or stackoverflow upvote. I am not using remote: true on those links, but rather I have an $.ajax call that handles the upvote like so:

var token = document.querySelector('meta[name="csrf-token"]').content;

$.ajax({
  // For the upvote, type will be POST
  type: $this.data('method'),
  beforeSend: function(xhr) {
    xhr.setRequestHeader('X-CSRF-Token', token)
  },
  url: $this.data('url'),
  success: function(data) {
    // Some cleanup...
  }
}); 

Once a logged out visitor tries to upvote, it fires the ajax request which is then halted (not authorized) and redirected, like this:

Started POST "/upvotes/toggle_vote"
Processing by UpvotesController#toggle_vote as */*
Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms)


Started GET "/users/sign_up"
Processing by RegistrationsController#new as */*

Here's the Devise controller which I've overwritten:

class RegistrationsController < Devise::RegistrationsController

  def new
    # ... other code        

    respond_to do |format|
      format.js   { render layout: false }
      format.html { respond_with self.resource }
    end
  end
end

Inside of /views/devise/registrations I have new.js.erb which opens up the "how would you like to sign up?" modal.

WHAT I'VE TRIED:

  • I don't think solving it by adding protect_from_forgery except: :new is the right answer (as has been proposed in similar questions), since that's inherently not safe.

  • I tried reordering the respond_to formats per this but that makes the signup modal not open.

  • I tried to throw in a format.any { raise ActionController::RoutingError.new("Not Found") } catch-all in the respond_to block but that did nothing to fix the error.

  • As you can see in the $.ajax call above I even try to set the X-CSRF-Token header.

The full error text by the way is this:

ActionController::InvalidCrossOriginRequest: Security warning: an embedded <script> tag on another site requested protected JavaScript. If you know what you're doing, go ahead and disable forgery protection on this action to permit cross-origin JavaScript

Any ideas?

Could it be that the authenticity token is getting lost since UpvotesController#toggle_vote redirects to RegistrationsController#new and changes from a POST to a GET?



from Rails ActionController::InvalidCrossOriginRequest on a js request

No comments:

Post a Comment