How can I stop sending a preflight request on a redirect?

811 Views Asked by At

I discovered that six years ago, the previous developer commented out this line of code (Ruby, Rails):

#protect_from_forgery

I replaced it with the default:

protect_from_forgery with: :exception

and now I mysteriously get the following error when I try to add items to my cart while logged out:

Access to XMLHttpRequest at 'https://id.foo-staging.com/openid/checklogin?return_to=http%3A%2F%2Flocalhost.foo-staging.com%3A3000%2Fcart%2Fitems' (redirected from 'http://localhost.foo-staging.com:3000/cart/items') from origin 'http://localhost.foo-staging.com:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.

I've pinned down that this is happening because of the following lines:

def get_user_identity_from_open_id_server
  redirect_to "#{OPEN_ID_PROVIDER_URL}/openid/checklogin?return_to=#{Rack::Utils.escape(request.url)}"
end

def open_id_authentication
  #stuff
  get_user_identity_from_open_id_server
end

before_filter :open_id_authentication

I understand what causes a preflight request, at a very high level, thanks to the documentation. But I don't think I'm doing any of those things.

* the request method is anything other than GET, HEAD, or POST
* you’ve set custom request headers other than Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, or Width
* the Content-Type request header has a value other than application/x-www-form-urlencoded, multipart/form-data, or text/plain

So my initial question is how do I determine what is triggering the preflight request, and then maybe I can figure out how to prevent it from happening. Is this a situation that I can change on my end, or does something need to change on id.foo-staging.com (which I don't have access to, but could probably ask the right person to fix it for me).

I've been Googling all day, and nothing seems to make any sense to me, especially because I can't pin down precisely what's wrong.

I can solve the issue with this code:

skip_before_filter :open_id_authentication, :only => [:create], :if => :current_user and :anonymous_cart

But I have to assume that this is unsafe, from a security standpoint?

ETA: This is what I see on the Network tab for this request:

General:

Request URL: https://id.foo-staging.com/openid/checklogin?return_to=http%3A%2F%2Flocalhost.foo-staging.com%3A3000%2Fcart%2Fitems Referrer Policy: no-referrer-when-downgrade

Request Headers:

Provisional headers are shown Access-Control-Request-Headers: x-requested-with Access-Control-Request-Method: GET Origin: http://localhost.foo-staging.com:3000 Referer: http://localhost.foo-staging.com:3000/p/Product0/1?id=1&slug=Product0 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36

Query String Parameters:

return_to: http://localhost.foo-staging.com:3000/cart/items

I presume the problem is the x-requested-with request header. But I don't know how to resolve this.

EATA:

Many JavaScript frameworks such as JQuery will automatically send this header along with any AJAX requests. This header cannot be sent cross-domain:

I guess my only option is to figure out how to rewrite this without AJAX?

1

There are 1 best solutions below

1
Indrajit Bhaskaran On

To avoid the preflight request you have to remove x-requested-with header but the error that you have is because the response location in the preflight call is different from the Origin. To fix the problem, update your code to use the new URL as reported by the redirect, thereby avoiding the redirect.