-
Notifications
You must be signed in to change notification settings - Fork 22.5k
-
Notifications
You must be signed in to change notification settings - Fork 22.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Content bug: Inaccurate explanation on request credentials #13063
Comments
Do you have a minimal reproducible test case or demo you can post as a comment here to demonstrate that behavior? I’m aware of https://zellwk.com/blog/how-fetch-credentials-handles-cookies/ and https://github.com/zellwk/demos/tree/main/fetch-credentials but I think it’s unlikely that other contributors will go through all that in order to extract a minimal reproducible test case. I can say with confidence that every test I have personally ever run with the Fetch API confirms the opposite of what’s asserted in the issue description here; that is, the Fetch API in fact does not send credentials in requests unless sending of credentials is explicitly requested in the call to the API. |
@sideshowbarker Gladly. Here's a reduced test case. https://github.com/zellwk/demos/tree/main/fetch-credentials-mdn/fetch-omit-credentials There are two folders — frontend and server. Please run both servers at the same time. I've detailed what to watch out for in frontend's |
Regarding the second point: Here's a reduced test case: https://github.com/zellwk/demos/tree/main/fetch-credentials-mdn/cookies-no-need-credentials |
Given that The browser first sends the request to the server — before the server sends back any response. So if the The browser doesn’t — and can’t — somehow wait to send credentials until after it gets backs a response from the server and checks whether or not that response has a So, Is there somewhere in the Or are you proposing that we update the If not, what specific changes are you imagining need to be made instead?
I see that all of the So it seems unclear what that test case is intended to test. One of your earlier comments said this:
Do you have a test case which demonstrates that? As far as I can see, the https://github.com/zellwk/demos/tree/main/fetch-credentials-mdn/cookies-no-need-credentials test case is not attempting to demonstrate that — because all of the |
I'm sorry if I didn't make this clear. Let me make as clear as I can. Thank you for your patience in reading this through and helping me work through this issue that I'm voicing. Point 1: Authorisation headers were sent regardless whether 'credentials' were set to omit, same-origin, or include.I want to refer you to this reduced test case: https://github.com/zellwk/demos/tree/main/fetch-credentials-mdn/fetch-omit-credentials. Please note that the credentials were set to This part in Request Credentials mentioned that Unfortunately, this is not true as demonstrated in the reduced test case, since I could send Authorization headers with credentials set to Please feel free to correct me if I misunderstood anything. Point 2: Access-Control-Allow-Credentials is not needed to send credentials between subdomains and domains
This was created by my misunderstanding on what I was confused because cross-origin requests required this header before cookies can be sent, but they were not required between subdomains and domains. Technically, a change in domain name (including adding subdomains) constitutes a change in origin, as mentioned in the Origin Glossary page. But in this case, even though there is a change in "origin", cookies are still sent without the The second test case (https://github.com/zellwk/demos/tree/main/fetch-credentials-mdn/cookies-no-need-credentials) was created to prove the point that we don't need the What makes it confusing is: Cookies work on a cross-site basis, not a cross-origin basis. (Referring to Site) documentation. But most of the docs speak about Credentials as if they're always cross-origin. If we do not require But the
If correcting the language (cross-site vs cross-origin) is too huge of a change, then I would suggest writing the fact that the I hope this communicates what I'm trying to say better. |
@sideshowbarker Just wondering if you saw the response above? |
I did see it, yes I think what would be most productive at this point would be if you could go ahead and create a pull request with some proposed changes. That’d give something concrete to consider |
Gotcha. Just FYI: Lots of work piling up recently, but I'm going to come back to this when I find some time/space to work on it. |
I recently also stumbled upon this issue. First of all, I can confirm @zellwk's testing results about However, it seems the current MDN explanation actually aligns with W3C: https://fetch.spec.whatwg.org/#concept-request-credentials-mode
Then definition of 'credentials': https://fetch.spec.whatwg.org/#credentials
Definition of 'authentication entries': https://fetch.spec.whatwg.org/#authentication-entry
RFC of 'HTTP authentication': https://httpwg.org/specs/rfc7235.html
And the whole idea of HTTP authentication being part of 'credentials' was reinforced by whatwg/fetch#612 whatwg/fetch#616 I know it must be me who overlooked something other than all the mature server/browser implementations out there, but really I wasn't able to find any supporting documentations on the reason why |
By the way I did a quick search in Firefox's code and I was only able to see how request credential mode interacts with cookies [1] at my first glance; though after digging a bit deeper, I'm wondering if things like [2][3] are relevant as well... [1] https://hg.mozilla.org/mozilla-central/file/a8e5c045d25c0161632683b641c64c7d073fdc91/dom/fetch/FetchDriver.cpp#l593 |
@Frederick888 Thanks for chiming in on this issue. It's reassuring to know I'm not alone in surfacing this issue. |
Ah I think I understand where the MDN wording (and W3C) came from now. 'HTTP Authentication' here, I believe, refers to the (usually) challenge-response form of HTTP native authentication, where users are often presented with a pop-up dialogue to provide username and password, then the 'credential' is cached by the browser for a certain period of time. (I've attached a simple python server so anyone who's not familiar with this flow can try it out.) Indeed in this scenario, credential is passed to server via To test this out, still using the attached testing server, first navigate to https://httpbin.org (I'm using httpbin simply cos it hasn't got script security headers, you can use others), then in developer console: resp = await fetch('http://localhost:9001', { mode: 'cors' } })
await resp.text()
// "needs auth!"
resp = await fetch('http://localhost:9001', { mode: 'cors', credentials: 'include' } })
// you can see a pop-up dialogue here
await resp.text()
// "secret!"
resp = await fetch('http://localhost:9001', { mode: 'cors', credentials: 'include' } })
// this time 'credential' is cached! back-end sees the cached Authorization header
await resp.text()
// "secret!"
resp = await fetch('http://localhost:9001', { mode: 'cors' } })
// cached 'credential' is omitted!
await resp.text()
// "needs auth!" But then actually you can use // you can also modify BE code first to omit Access-Control-Allow-Credentials
resp = await fetch('http://localhost:9001', { mode: 'cors', headers: { 'Authorization': 'Basic foo' } } })
await resp.text()
// "secret!" In conclusion, instead of saying (Modified from https://gist.github.com/mdonkers/63e115cc0c79b4f6b8b3a6b797e485c7) #!/usr/bin/env python3
"""
Very simple HTTP server in python for logging requests
Usage::
./server.py [<port>]
"""
from http.server import BaseHTTPRequestHandler, HTTPServer
import logging
class S(BaseHTTPRequestHandler):
def _set_response(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.send_header("Access-Control-Allow-Credentials", "true")
self.send_header("Access-Control-Allow-Headers", "Content-Type,Authorization")
self.send_header("Access-Control-Allow-Origin", "https://httpbin.org")
self.end_headers()
def _set_challenge(self):
self.send_response(401)
self.send_header("WWW-Authenticate", "Basic")
self.send_header("Content-type", "text/html")
self.send_header("Access-Control-Allow-Credentials", "true")
self.send_header("Access-Control-Allow-Headers", "Content-Type,Authorization")
self.send_header("Access-Control-Allow-Origin", "https://httpbin.org")
self.end_headers()
def do_GET(self):
logging.info(
"GET request,\nPath: %s\nHeaders:\n%s\n", str(self.path), str(self.headers)
)
if self.headers.get("Authorization") is not None:
# allow any user/pass
self._set_response()
self.wfile.write("secret!".encode("utf-8"))
else:
self._set_challenge()
self.wfile.write("needs auth!".encode("utf-8"))
def do_OPTIONS(self):
logging.info(
"OPTIONS request,\nPath: %s\nHeaders:\n%s\n",
str(self.path),
str(self.headers),
)
self._set_response()
self.wfile.write("OPTIONS request for {}".format(self.path).encode("utf-8"))
def run(server_class=HTTPServer, handler_class=S, port=8080):
logging.basicConfig(level=logging.INFO)
server_address = ("", port)
httpd = server_class(server_address, handler_class)
logging.info("Starting httpd...\n")
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
logging.info("Stopping httpd...\n")
if __name__ == "__main__":
from sys import argv
if len(argv) == 2:
run(port=int(argv[1]))
else:
run() |
See #34437 (comment). |
What page(s) did you find the problem on?
Specific page section or heading?
What is the problem?
There are a few problems:
omit
,same-origin
, orinclude
.Access-Control-Allow-Credentials
page mentioned that credentials are cookies, authorization headers, or TLS client certificates.A few things here:
Access-Control-Allow-Credentials
are not required for Authorization headers. They can be sent regardless whetherAccess-Control-Allow-Credentials
is present.Authorization
to be includedAccess-Control-Allowed-Headers
.Access-Control-Allow-Credentials
are not required to send cookies between domains and subdomains. This is not listed anywhere but I thought it'll be good to make things clear.What did you expect to see?
Three things:
Did you test this? If so, how?
I tested
credentials
and wrote an article about my tests. I focused on cookies in this article and didn't include the Authorization header parts. There's a test repository included in the article. I can create a test repo for the authorization part if necessary. Just let me know.The text was updated successfully, but these errors were encountered: