0

Scenario

We have some Javascript hosted by a third-party CMS service, and we have some data on a server under our control. When a user is accessing the CMS via a browser (and executing our Javascript), we would like to make a cross-origin GET request to our server and have the server respond with the correct Access-Control-Allow-Origin header so that the browser accepts the response.

Problem

When we inspect requests going from the CMS to our server, the request's Origin header is set to null. So we can't set a value for Access-Control-Allow-Origin other than * to make the browser accept the response. We're not really sure why the value is null. The JS is executing in an environment that we don't fully control.

Potential Solution

We're working under the assumption that the Origin will always be null, and there's nothing we can do to change it. The best solution we can come up with is defining a pre-shared secret. When the browser makes the cross-origin request, it adds a custom header with the secret. The server looks for that header, and if the secret matches, the server adds the response header Access-Control-Allow-Origin: *.

Is there a better, more secure way to handle this situation?

Sam Jones
  • 160
  • 9
  • You can create a proxy endpoint on your server that will accept the request from your JS, and make a request to the third-party CMS service using `curl` – Alon Eitan Feb 10 '17 at 19:03
  • 1
    Why is the origin `null`? This would be the case if the requesting resource is `file:///...` – Andreas Feb 10 '17 at 19:03
  • All requests by browser will have a Referer header – charlietfl Feb 10 '17 at 19:05
  • @Andreas So if you're correct, that mean that they can make no ajax request at all, right? – Alon Eitan Feb 10 '17 at 19:06
  • @AlonEitan We don't need to make a request to the CMS. We need to make a request from the CMS JS to our server. – Sam Jones Feb 10 '17 at 19:06
  • @Andreas You're correct, but we're not running the JS from a file in this case. – Sam Jones Feb 10 '17 at 19:07
  • FYI, `null` is part of the specification and you can return `Access-Control-Allow-Origin: null`. That has all the same security implications as `*`, though. – Kevin Christopher Henry Feb 10 '17 at 19:54
  • As far as the Referer header, you can’t depend on it. Users can choose to have their browsers not send it http://kb.mozillazine.org/Network.http.sendRefererHeader (and to suppress document.referrer too) , and there are lots of other conditions in which it may be empty https://stackoverflow.com/questions/6880659/in-what-cases-will-http-referer-be-empty/6880668#6880668. And in browsers that support Referer Policy, authors can also cause the Referer header to be empty https://stackoverflow.com/questions/6880659/in-what-cases-will-http-referer-be-empty/28836003#28836003. – sideshowbarker Feb 11 '17 at 00:50
  • @SamJones In current browsers, JavaScript running from a `file:` origin can make requests using XHR and the Fetch API and it’ll work. But I see you say the `null` cases you’re seeing come from requests made by code running at a CMS. In that case I’d guess the requests are made from sandboxed iframes that lack the `allow-same-origin` header. Otherwise, browsers also send `Origin: null` for requests from *any* non-http/https origins; for example, pages opened from `data:` URIs. – sideshowbarker Feb 11 '17 at 01:48
  • Another case where you’ll end up with `Origin: null` is for requests that get redirected across origins. For example, if from XHR in my JS I make a request to `http://example.com/api` and that gets redirected to `http://api.example.com`, then `Origin` will get set to `null` in that case. – sideshowbarker Feb 11 '17 at 09:53

1 Answers1

0

You need to get the value of the request Referer header which is set by the browser and use that for the response Access-Control-Allow-Origin header value

charlietfl
  • 170,828
  • 13
  • 121
  • 150