go: net/http: client does not send cookies if an intermediary request hits a different domain
What version of Go are you using (go version)?
1.10.2
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env)?
Windows 10 and OSX
What did you do?
I have the following scenario:
- HTTP Client makes a request to
http://domain-a/set - HTTP Handler at
http://domain-a/setsets a Cookie and redirects tohttp://domain-b/foo - HTTP Handler at
http://domain-b/foodoes nothing except redirecting back tohttp://domain-a/check - HTTP Header at
http://domain-a/checkis missing the cookie
The cookie is set if we do not redirect to http://domain-b but directly to http://domain-a:
- HTTP Client makes a request to
http://domain-a/set - HTTP Handler at
http://domain-a/setsets a Cookie and redirects tohttp://domain-a/check - HTTP Header at
http://domain-a/checkhas the cookie set
A reproducible demo is available on gist.
I believe that this is caused by some logic that is tied to:
// • when forwarding sensitive headers like “Authorization”, // “WWW-Authenticate”, and “Cookie” to untrusted targets. // These headers will be ignored when following a redirect to a domain // that is not a subdomain match or exact match of the initial domain. // For example, a redirect from “foo.com” to either “foo.com” or “sub.foo.com” // will forward the sensitive headers, but a redirect to “bar.com” will not.
My intuition tells me that the cookie header is deleted if the client encounters a domain that does not match the original domain, and does not recover the cookie in subsequent redirects if the domain is set back to the original one.
From what I can tell, this behaviour could be caused by shouldCopyHeaderOnRedirect which strips all the info and thus makes it unavailable in subsequent requests.
What did you expect to see?
I expected the cookie to be available at localhost:9000 (this is not about the intermediary domain localhost:8000), even if one of the redirects (in the middle) is a different domain. This is the default behavior of browsers too.
What did you see instead?
The cookie was not set.
edit://
While this is an edge case, it is kind of common in scenarios with federation where the browser does a lot of redirects between domains. That’s actually how I found this issue.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 18 (8 by maintainers)
@arekkas No need to apologize, this happens 😃 I’m glad it is working now.
I think there is a misunderstanding here. I’ll try to be as concise as possible in the description.
I have a cookie jar that has cookies for
domain-a. I expect that these cookies are always sent todomain-awhen making a request todomain-a, regardless of any prior redirections.What happens instead is that, if I have a cookie jar with cookies for
domain-a, the cookies will be stripped if - somewhere inbetween - a request to another domain (e.g.domain-b) was made.From the opening post:
http://domain-a/set. (Here, a cookie fordomain-awill be set in the cookiejar).http://domain-a/setsets a Cookie and redirects tohttp://domain-b/foohttp://domain-b/foo. No cookies are included. This is expected and required and ok.http://domain-b/foodoes nothing except redirecting back tohttp://domain-a/checkhttp://domain-a/checkis missing the the cookie from the cookie jar fordomain-a. (Here, we’d expect the cookies fordomain-ato be included because the prior redirection should not affect whether or not legitimate cookies are sent todomain-aor not. The proper cookies should always be included in requests todomain-aif the cookies are in fact set fordomain-a)I hope this clarifies the confusion.
Seems fixable (making sure we set/get cookies from the
Jarper request across redirects), but not for Go 1.11.