HTTP Auth request fails in browser due to CORS, ok in Node

喜欢而已 提交于 2021-02-09 10:39:00

问题


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?

回答1:


The server is misconfigured. It’s not properly CORS-enabled. To be properly CORS-enabled it must respond to unauthenticated OPTIONS requests with a 200 or 204 status code.

Request isn’t “failing” to pass credentials in the OPTIONS preflight request. Request isn’t even making the the OPTIONS request. Instead the browser engine is, on its own.

And specifying the credentials flag for the request in your own code doesn’t cause credentials to get added to the preflight OPTIONS request. Instead, credentials only get added to the GET request from your own code — that is, if the preflight has succeeded and the browser actually ever moves on to making that GET request.

That’s because the CORS-protocol requirements in the Fetch specify that browsers must omit all credentials from preflight OPTIONS requests.

See https://fetch.spec.whatwg.org/#ref-for-credentials%E2%91%A5:

a CORS-preflight request never includes credentials

So the behavior you’ve encountered is intentional, by design.

For a related explanation in more detail, see the answer at HTTP status code 401 even though I’m sending an Authorization request header.



来源:https://stackoverflow.com/questions/50942883/http-auth-request-fails-in-browser-due-to-cors-ok-in-node

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!