I'm working on a chrome application that will be communicating with the server through RESTful API.
Without adding the server URL to the permissions in the manifest.json I can see that Chrome sends all requests with the origin header (chrome-extension://cpndc....) and if any of these requests has non - standard headers it also sends a preflight OPTIONS request - this is all as expected.
After adding the domain to the permissions, preflight OPTIONS is not sent anymore. The origin header is not present in the GET calls but it is still present in POST, PATCH, MERGE calls.
This causes problems as the CORS implementation on the server I will use assumes that requests with origin header are CORS requests and responds with 403 error as it doesn't like the origin - this origin with chrome-extension is not on the list of accepted origins.
As per the CORS specification, the expectation is that the origin header should be only added in cross domain request https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS#Origin but since the server domain is added to the permissions, I would expect that not only GET but also other requests don't have it.
The question is: is this a bug in Chrome Apps CORS implementation?
Summary of my findings when working with Chrome Apps:
If endpoint URL is not added to the permissions in the manifest file (CORS will kick in): - Chrome App sends the origin header in all type of requests - Chrome App sends the OPTIONS preflight for all requests that have non-standard headers
If endpoint URL is added to the permissions in the manifest file (security for requests to that domain is off) - Chrome Apps doesn't send the OPTIONS preflight anymore (as expected) - Chrome App sends the origin header in non-GET requests only (should not send origin at all)
Example permissions file:
"permissions": [
"http://api.randomuser.me/*"
]
Example app code:
window.onload = function() {
function get(){
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://api.randomuser.me/?seed=bigFish", true);
xhr.setRequestHeader('Authn', 'abcdefghijklmnopqrstuvxyz');
xhr.onload = function (e) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log(xhr.responseText);
} else {
console.error(xhr.statusText);
}
post();
}
};
xhr.onerror = function (e) {
console.error(xhr.statusText);
};
xhr.send(null);
}
function post() {
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://api.randomuser.me/', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('Authn', 'abcdefghijklmnopqrstuvxyz');
xhr.onload = function () {
// do something to response
console.log(this.responseText);
};
xhr.send('user=person&pwd=password&organization=place&requiredkey=key');
}
document.getElementById('mybutton').addEventListener('click', function() {
get();
});
};
GET request without the origin header:
POST request with the origin header: