I'm stuck trying to diagnose a problem where a GET request with HTTP Basic Auth succeeds in Node, but fails in the browser. The problem manifests directly as a CORS failure (there's no Access-Control-Allow-Origin on the 401 page).
request.js:119 OPTIONS http://HOST?PARAMS 401 (Unauthorized)
ClientRequest._onFinish @ request.js:119
(anonymous) @ request.js:61
...
17:53:59.170 localhost/:1 Failed to load http://HOST?PARAMS: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9966' is therefore not allowed access. The response had HTTP status code 401. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
The request looks like this:
const request = require("request-promise");
const options = {"url":"http://...?","auth":{"user":"...","pass":"..."},"json":true,"qs":{...},"headers":{},"resolveWithFullResponse":true}
request.get(options).then(...);
How this request shows up in Chrome:
What's surprising here to me:
- The method is OPTIONS, not GET. (Which I didn't explicitly ask for.)
- My auth credentials are not included in the headers (even though I haven't set
sendImmediately: false
- The "Provisional headers are shown" warning.
What I would like to know:
- Is this expected behaviour?
- If not, what's going wrong?
- If yes, what's going wrong? :)
Running what would be the equivalent request on the command line seems to work fine:
curl -I 'http://MYUSERNAME:MYPASSWORD@SAMEURL?SAME=PARAMETERS' -H 'Origin: http://localhost:4466' -X OPTIONS
HTTP/1.1 200 OK
Date: Wed, 20 Jun 2018 07:29:28 GMT
Server: Apache-Coyote/1.1
Access-Control-Allow-Origin: http://localhost:4466
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: Access-Control-Allow-Origin,Access-Control-Allow-Credentials
Vary: Origin
X-Frame-Options: SAMEORIGIN
Allow: GET,HEAD,POST,OPTIONS
Content-Length: 0
However I notice that without the credentials supplied in the URL, there are no CORS headers on the response:
HTTP/1.1 401 Unauthorized
Date: Wed, 20 Jun 2018 07:45:26 GMT
Server: Apache/2.4.29 (Unix) OpenSSL/1.0.2l
WWW-Authenticate: Basic realm="Authentication Required"
Content-Length: 381
Content-Type: text/html; charset=iso-8859-1
Is that the correct behaviour?
Hypothesis
I suspect:
- The browser is sending the OPTIONS "pre-flight" request because it has to, because the request is not a "simple request". (Not totally clear if this is the request library or the browser itself doing this)
- The server is responding 401 because credentials weren't supplied, but isn't adding the CORS headers that it should.
- Without the CORS headers the browser prevents the Request library accessing the result, so it can't complete the authentication.
What I'm not sure about:
- Is the server misconfigured?
- Is Request failing to pass credentials in the OPTIONS preflight request?