Dynamic import request loses cookie on after 304 response
Reported by
aapo.ala...@gmail.com,
Jan 19
(3 days ago)
|
||||
Issue descriptionUserAgent: 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.
,
Yesterday
(43 hours ago)
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.
,
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.
,
Yesterday
(41 hours ago)
type=module fetches an object without credentials (Sending them or setting them), I believe.
,
Yesterday
(41 hours ago)
,
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 |
||||
Comment 1 by aapo.ala...@gmail.com
, Jan 19 (3 days ago)