I have a client-side JS application that is making signed OAuth1.0a GET requests our own internal API. I know that generally you would use a proxy server or something to do this but do to limitations we must do all this on the client-side (using oauth-1.0a
to sign the requests).
I am no expert with CORS issues, and generally in the past when this issue has come up backend teams have set Access-Control-Allow-Origin: *
, everything worked as expected and we'd call it a day. Sadly the issues are persisting, and I think the root of the issue is the gap in my understanding of CORS/OAuth requests.
Below is a function that wraps the request in a Promise:
const fetch = (url) => {
// the request data to be signed
const reqData = { method: 'GET', url: url };
// now we sign the request
// more details on this method: https://github.com/ddo/oauth-1.0a
const auth = oauth.authorize(reqData);
// generates the auth headers for us
const authHeader = generateAuthHeaders(auth);
// returns a promise that:
// - resolves if valid data it returned
// - rejects if request fails for any reason
return new Promise((res, rej) => {
const r = new XMLHttpRequest();
r.open('GET', url, true);
// Setting to true results in this error:
// "A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true."
r.withCredentials = false;
// Adding the Authorization request header
r.setRequestHeader('Authorization', authHeader);
// Listen for a response
r.onreadystatechange = () => {
if (r.readyState === 4) {
if (r.status === 200) {
return res(r.responseText);
}
return rej(new Error(`Request to ${url} failed!`));
}
};
r.send(null);
});
};
About half the time this works and returns data as expected. But the rest of the time it fails with a 401 error on the preflight OPTIONS request. Why is the issue not occurring every time? What am I doing wrong?
Edit: The backend team has set up the servers/load balancers correctly, so this is not an issue of one server in the balancer being mis-configured.