1

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.

Dave Lunny
  • 750
  • 8
  • 21
  • 1
    This sounds like a configuration error on the server side. If it works half the time on an identical request, I would suspect you have two servers behind a load balancer and one of them is misconfigured. – Jon B May 02 '16 at 16:11
  • @JonB the server config is shared across all servers/the same one is used when a server gets initialized... they are suggesting it might be that my generated oauth timestamp/nonce might be the same for both the OPTIONS preflight req and the GET request that follows... – Dave Lunny May 02 '16 at 17:27
  • A pre-flight request does not contain auth. The server should be configured to allow anonymous access for OPTIONS. I'm not sure why you're getting different behavior between requests, but you should never get a 401 on OPTIONS. See here: http://stackoverflow.com/questions/15734031/why-does-the-preflight-options-request-of-an-authenticated-cors-request-work-in – Jon B May 02 '16 at 17:40
  • @JonB you are correct the OPTIONS request never sends auth, my bad. It's always the actual GET request that gets that 401's (even though the correct auth stuff is sent with the GET request). – Dave Lunny May 02 '16 at 17:48

0 Answers0