WICG / private-network-access

https://wicg.github.io/private-network-access/
Other
52 stars 21 forks source link

Specifying headers in fetch() request immediately causes it to fail #131

Closed RBastianini closed 3 months ago

RBastianini commented 4 months ago

I'm not sure whether this is intended by the specification (I've read the explainer and all the open and closed issues, but I couldn't find mention of this): I've found out that if I add a Content-Type or Authorization header to the fetch options object, the request immediately fails with the following error message:

Access to fetch at 'http:\/\/private-network-device-hostname/cgi-bin/epos/service.cgi?devid=local_printer&timeout=60000' from origin 'https:\/\/some-public-domain' has been blocked by CORS policy: Request had a target IP address space of unknown yet the resource is in address space unknown.

on Chrome Version 123.0.6312.28 (Official Build) beta (64-bit).

This is not caused by a wrong OPTIONS response from the private network device, because no CORS request is ever made to it (I double-checked with a network sniffer) and of course I have specified targetAddressSpace: 'private' in the options. If I forcefully empty the headers option, and repeat the same request, I instead get the PNA prompt and I can execute the request (although it still fails because I really need the Authorization header).

Am I doing something wrong? Is this the expected behaviour?

Thanks.

jub0bs commented 4 months ago

Could you provide a minimal reproducible example?

RBastianini commented 4 months ago

Sure, here is a working example:

<html>
<head>
</head>
<body>
<button onClick="testPNA()">Test PNA</button>
<script>
var testPNA = function () {
  request = fetch(
        'http://192.168.1.246/cgi-bin/epos/service.cgi?devid=local_printer&timeout=60000',
        {
            headers: new Headers({
              'Accept-Encoding': 'gzip, deflate',
//            'Content-Type': 'text/xml',
//            'Host': 'device.local',
//            'Authorization': 'Basic dGVzdDp0ZXN0',
              'Origin': 'https://riccardo.bastianini.me',
            }),
            targetAddressSpace: 'private',
            credentials: 'omit',
            cache: 'no-cache',
            mode: 'cors',
            method: 'POST',
            body: '<?xml version="1.0" encoding="UTF-8"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><epos-print xmlns="http://www.epson-pos.com/schemas/2011/03/epos-print"></epos-print></s:Body></s:Envelope>'
        }
    );
  request.then((s) => s.text().then(console.log));
}
</script>
</body>
</html>

and here's this test page. Even if you don't have a device on that IP address you can see the request being sent and taking some time to complete. immagine

Conversely, if you uncoment any of the three commented lines, like in this test page no request is made and you immediately get the error message.

immagine

jub0bs commented 4 months ago

@RBastianini Thanks. I'm getting a 504 error from your second test page, though.

Also, although this may be unrelated to your issue, be aware that Host and Origin are forbidden request-header names; attempts by browser-based clients to include them in requests are futile.

RBastianini commented 4 months ago

I removed the headers you mentioned from my test pages, but the issue is the same. My hosting is having a rough morning, so I guess the pages won't be available while they resolve the issue.

jub0bs commented 4 months ago

Another thing: for better accessibility, please consider posting error messages as text rather than as images.

y3nd commented 4 months ago

Same issue here on Chrome and Edge (both 123)

Full error is

Access to fetch at 'http://192.168.0.50:3000/ping' from origin 'https://example.com' has been blocked by CORS policy: Request had a target IP address space of `unknown` yet the resource is in address space `unknown`.

No issue by removing all the "custom" headers in the fetch options

jub0bs commented 4 months ago

@y3nd Have you configured http://192.168.0.50:3000/ping for private-network access? If not, the browser is working as expected.

y3nd commented 4 months ago

Yes, everything is working well (prompt, GET/POST requests, CORS) except when one or multiple HTTP header(s) are added. I'm testing with the "Content-Type" header, which is configured in the Access-Control-Allow-Headers header. As @RBastianini said, the browser is not even sending any OPTIONS request to check if the server has been configured properly for PNA.

jub0bs commented 4 months ago

@y3nd I cannot reproduce, at least not in Chromium 123.0.6312.58. Which version of Chromium does your browser rely on?

In my case, the request is failing because of mixed content:

Mixed Content: The page at 'https://riccardo.bastianini.me/pna-test-not-working.html' was loaded over HTTPS, but requested an insecure resource 'http://192.168.1.246/cgi-bin/epos/service.cgi?devid=local_printer&timeout=60000'. This request has been blocked; the content must be served over HTTPS.

No mention of PNA at all.

y3nd commented 4 months ago

@jub0bs I get this behavior either if the client has not the trial token set or if the flag #private-network-access-permission-prompt is not enabled. Try using one of them, they allow mixed content relaxing (secure context requesting a non-secure server).

I'm on Chrome 123.0.6312.86 but same issue (with headers) occurs on Edge 123.0.2420.65

RBastianini commented 4 months ago

@jub0bs I can confirm the same happens on Chromium version 123.0.6312.58 (Official Build) snap (64-bit). You do need to manually enable the related PNA flag though, my domain is not enrolled in the origin trial for it.

iVanlIsh commented 3 months ago

The permission prompt is shipped in M124 and only in Origin Trial in M123. So you need to enable the trial or by feature flag in M123

y3nd commented 3 months ago

Sorry why closing the issue ? @iVanlIsh

RBastianini commented 3 months ago

Thanks for the reply @iVanlIsh, but the missing header is not the issue. I have manually enabled the chrome flag to test PNA, and since your reply I have signed up for origin trial and added the required headers to my example pages linked above and I can still reproduce. :(

iVanlIsh commented 3 months ago

oh sorry I thought the issue is solved. Let me take a closer look.

iVanlIsh commented 3 months ago

Did you add the Access-Control-Request-Private-Network: true header?

RBastianini commented 3 months ago

Shouldn't the header be added automatically when specifying targetAddressSpace: 'private' as fetch option? I believe this should be a forbidden request header, so I shouldn't be able to add it directly. Anyway, even if I manually add it, it doesn't seem to change the behaviour of the non-working test page.

y3nd commented 3 months ago

The issue is fixed on Version 125.0.6410.0 (Official Build) canary (64-bit)

Not fixed on Version 124.0.6367.29 (Official Build) beta (64-bit) and Version 123.0.6312.123 (Official Build) (64-bit)

RBastianini commented 3 months ago

Thanks @y3nd, I can confirm it's fixed on Chrome Canary. :+1: