New issue
Advanced search Search tips

Issue 923661 link

Starred by 1 user

Issue metadata

Status: Unconfirmed
Owner: ----
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Windows
Pri: 2
Type: Bug



Sign in to add a comment

Dynamic import request loses cookie on after 304 response

Reported by aapo.ala...@gmail.com, Jan 19 (3 days ago)

Issue description

UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36

Steps to reproduce the problem:
I am trying to use ES6 dynamic import to load additional scripts for an app that requires authentication. The code is in a script tag with no 'type="module"' set. The dynamic imports naturally use SAMEORIGIN as their CORS rule. When a script is imported for the first time, Chrome sets the authentication cookie to the request header as expected and we get a status code 200 response with the data.

If we now refresh the page, then this time when we import the script, Chrome still successfully sets the cookie to the request header, and this time we get a response of 304 from our If-None-Match field matching to the response ETag, and Chrome uses the cached data.

If we refresh again, now the third time (and fourth, fifth, ... as well) we do the import, Chrome now does not set the cookie to the header, we're given a response of 401 and the importing of the script of course fails.

Here are the copy-pasted request-response pairs of the three imports that I get with the app.

1.

GET /app/resourcePath/resource HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Origin: http://localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
Accept: */*
Referer: http://localhost:8080/app/subapp/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,en-US;q=0.8,de;q=0.7,fi;q=0.6,ja;q=0.5,sv;q=0.4,fr;q=0.3,nb;q=0.2
Cookie: name=[bytes redacted]
If-None-Match: W/"36e9-ToFtyvZxrZJNlYoHttVC3zRXh/4"

HTTP/1.1 304 Not Modified
Server: nginx/1.13.9
Date: Sat, 19 Jan 2019 14:13:57 GMT
Connection: keep-alive
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
ETag: W/"36e9-ToFtyvZxrZJNlYoHttVC3zRXh/4"
set-cookie: name=[bytes redacted]; Path=/; Expires=Tue, 19 Jan 2038 06:06:52 GMT; HttpOnly
X-Frame-Options: SAMEORIGIN

2. 

GET /app/resourcePath/resource HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Origin: http://localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
Accept: */*
Referer: http://localhost:8080/app/subapp/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,en-US;q=0.8,de;q=0.7,fi;q=0.6,ja;q=0.5,sv;q=0.4,fr;q=0.3,nb;q=0.2
Cookie: name=[bytes redacted]
If-None-Match: W/"36e9-ToFtyvZxrZJNlYoHttVC3zRXh/4"

HTTP/1.1 304 Not Modified
Server: nginx/1.13.9
Date: Sat, 19 Jan 2019 14:15:25 GMT
Connection: keep-alive
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
ETag: W/"36e9-ToFtyvZxrZJNlYoHttVC3zRXh/4"
set-cookie: name=[bytes redacted]; Path=/; Expires=Tue, 19 Jan 2038 06:08:20 GMT; HttpOnly
X-Frame-Options: SAMEORIGIN

3. 

GET /app/resourcePath/resource HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Origin: http://localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
Accept: */*
Referer: http://localhost:8080/app/subapp/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,en-US;q=0.8,de;q=0.7,fi;q=0.6,ja;q=0.5,sv;q=0.4,fr;q=0.3,nb;q=0.2
If-None-Match: W/"36e9-ToFtyvZxrZJNlYoHttVC3zRXh/4"

HTTP/1.1 401 Unauthorized
Server: nginx/1.13.9
Date: Sat, 19 Jan 2019 14:15:58 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 12
Connection: keep-alive
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Download-Options: noopen
ETag: W/"c-dAuDFQrdjS3hezqxDTNgW7AOlYk"

If I do a Hard Reload on the browser window, then the import again gets the cookie set and the first response is also a 304, the second import still gets the cookie set to the header and responds 304 as well. Once again on the third response the cookie is left out of the response, and a 401 follows.

What is the expected behavior?
Chrome sets the cookie to all same-origin import requests sent from a default type script.

What went wrong?
Chrome does not set cookie to dynamic import request sent from a default type script on subsequent requests after having received a 304 response on the second time.

Did this work before? N/A 

Does this work in other browsers? N/A

Chrome version: 71.0.3578.98  Channel: stable
OS Version: 10.0
Flash Version: 

Luckily while writing this bug report I found a workaround / fix, which is that setting the script doing the importing as `type="module"` causes Chrome to no longer lose the cookies on subsequent requests.
 

Comment 1 by aapo.ala...@gmail.com, Jan 19 (3 days ago)

This might also be somehow related to https://bugs.chromium.org/p/chromium/issues/detail?id=839720 as they seem a bit similar.

Comment 2 by vamshi.kommuri@chromium.org, Yesterday (43 hours ago)

Cc: eroman@chromium.org vamshi.kommuri@chromium.org
Components: Internals>Network>Cookies Internals>Network>Auth
Labels: Triaged-ET
Thanks for filing the issue!

As we aren't very sure about the steps to be followed in order to triage this further, hence adding appropriate components and cc'ing eroman@ from Issue 839720 for more inputs.

Comment 3 by aapo.ala...@gmail.com, Yesterday (43 hours ago)

Mm, the best "steps to be followed" I can give is:

1. From a `<script src="index.js"></script>` tag, run an `import("./other.js")` ES6 dynamic import with a login cookie enabled / required by the server. Verify that 202 occurs.
2. Refresh the page. Verify that a 304 response occurs for the "other.js" file.
3. Refresh the page. A 401 response should occur, as Chrome has not set the cookie to the request header.
4. Add `type="module"` to the "index.js" script tag.
5. Refresh the page. Verify that the cookie is once again properly set and a 304 response occurs.

I believe I got this to occur even with these pared down steps. (The real application is quite a bit more complex, more requests etc.) I can try to repeat the bug with the pared down steps again later, maybe during the weekend or some night this week.

The resemblance from 839720 would point to the set-cookie from the second request response (304) not being respected for some reason.

Comment 4 by mmenke@google.com, Yesterday (41 hours ago)

Components: -Internals>Network>Auth Blink>Loader
type=module fetches an object without credentials (Sending them or setting them), I believe.

Comment 5 by mmenke@google.com, Yesterday (41 hours ago)

Components: Blink>HTML>Script

Comment 6 by aapo.ala...@gmail.com, Yesterday (39 hours ago)

Sorry, you misunderstand. I do am not referring to the fetching of the "index.js" that is fetched by the way of a traditional script tag in the HTML.

I am referring to the request that is sent by the "index.js" script when that script uses the ECMAScript dynamic import, eg. `const x = await import("./x.js")`.

That request is should always have SAMEORIGIN and, as far as I understand, also always send any credentials for those same-origin fetches.

Sign in to add a comment