I am getting partial list of cookies with document.cookie when executing on subdomain. I would like to retrieve superdomain+subdomain cookies. Is there any way to do that?
Let say I have a domain
example.com
sub.example.com
And I have cookies set
name=value domain
c1=2 => .example.com
c2=4 => sub.example.com
If url in browser is sub.example.com I want to get all the above cookies how would I do that? document.cookie only returns c2=4
You are trying to access cookies from different domain. Browser not going to allow this. Please refer this.
Turns out there was a flag in browser which sets httponly cookie, This cookie is not visible from document.cookie javascript method for security reasons.
Related
Due to weird domain/subdomain cookie issues that I'm getting, I'd like to know how browsers handle cookies. If they do it in different ways, it would also be nice to know the differences.
In other words - when a browser receives a cookie, that cookie MAY have a domain and a path attached to it. Or not, in which case the browser probably substitutes some defaults for them. Question 1: what are they?
Later, when the browser is about to make a request, it checks its cookies and filters out the ones it should send for that request. It does so by matching them against the requests path and domain. Question 2: what are the matching rules?
Added:
The reason I'm asking this is because I'm interested in some edge cases. Like:
Will a cookie for .example.com be available for www.example.com?
Will a cookie for .example.com be available for example.com?
Will a cookie for example.com be available for www.example.com?
Will a cookie for example.com be available for anotherexample.com?
Will www.example.com be able to set cookie for example.com?
Will www.example.com be able to set cookie for www2.example.com?
Will www.example.com be able to set cookie for .com?
Etc.
Added 2:
Also, could someone suggest how I should set a cookie so that:
It can be set by either www.example.com or example.com;
It is accessible by both www.example.com and example.com.
Although there is the RFC 2965 (Set-Cookie2, had already obsoleted RFC 2109) that should define the cookie nowadays, most browsers don’t fully support that but just comply to the original specification by Netscape.
There is a distinction between the Domain attribute value and the effective domain: the former is taken from the Set-Cookie header field and the latter is the interpretation of that attribute value. According to the RFC 2965, the following should apply:
If the Set-Cookie header field does not have a Domain attribute, the effective domain is the domain of the request.
If there is a Domain attribute present, its value will be used as effective domain (if the value does not start with a . it will be added by the client).
Having the effective domain it must also domain-match the current requested domain for being set; otherwise the cookie will be revised. The same rule applies for choosing the cookies to be sent in a request.
Mapping this knowledge onto your questions, the following should apply:
Cookie with Domain=.example.com will be available for www.example.com
Cookie with Domain=.example.com will be available for example.com
Cookie with Domain=example.com will be converted to .example.com and thus will also be available for www.example.com
Cookie with Domain=example.com will not be available for anotherexample.com
www.example.com will be able to set cookie for example.com
www.example.com will not be able to set cookie for www2.example.com
www.example.com will not be able to set cookie for .com
And to set and read a cookie for/by www.example.com and example.com, set it for .www.example.com and .example.com respectively. But the first (.www.example.com) will only be accessible for other domains below that domain (e.g. foo.www.example.com or bar.www.example.com) where .example.com can also be accessed by any other domain below example.com (e.g. foo.example.com or bar.example.com).
The previous answers are a little outdated.
RFC 6265 was published in 2011, based on the browser consensus at that time.
Since then, there has been some complication with public suffix domains. I've written an article explaining the current situation - http://bayou.io/draft/cookie.domain.html
To summarize, rules to follow regarding cookie domain:
The origin domain of a cookie is the domain of the originating request.
If the origin domain is an IP, the cookie's domain attribute must not be set.
If a cookie's domain attribute is not set, the cookie is only applicable to its origin domain.
If a cookie's domain attribute is set,
the cookie is applicable to that domain and all its subdomains;
the cookie's domain must be the same as, or a parent of, the origin domain
the cookie's domain must not be a TLD, a public suffix, or a parent of a public suffix.
It can be derived that a cookie is always applicable to its origin domain.
The cookie domain should not have a leading dot, as in .foo.com - simply use foo.com
As an example,
x.y.z.com can set a cookie domain to itself or parents - x.y.z.com, y.z.com, z.com. But not com, which is a public suffix.
a cookie with domain=y.z.com is applicable to y.z.com, x.y.z.com, a.x.y.z.com etc.
Examples of public suffixes - com, edu, uk, co.uk, blogspot.com, compute.amazonaws.com
I tested all the cases in the latest Chrome, Firefox, Safari in 2019.
Response to Added:
Will a cookie for .example.com be available for www.example.com? YES
Will a cookie for .example.com be available for example.com? YES
Will a cookie for example.com be available for www.example.com? NO, Domain without wildcard only matches itself.
Will a cookie for example.com be available for anotherexample.com? NO
Will www.example.com be able to set cookie for example.com? NO, it will be able to set cookie for '.example.com', but not 'example.com'.
Will www.example.com be able to set cookie for www2.example.com? NO. But it can set cookie for .example.com, which www2.example.com can access.
Will www.example.com be able to set cookie for .com? NO
For an extensive coverage review the contents of RFC2965. Of course that doesn't necessarily mean that all browsers behave exactly the same way.
However in general the rule for default Path if none specified in the cookie is the path in the URL from which the Set-Cookie header arrived. Similarly the default for the Domain is the full host name in the URL from which the Set-Cookie arrived.
Matching rules for the domain require the cookie Domain to match the host to which the request is being made. The cookie can specify a wider domain match by include *. in the domain attribute of Set-Cookie (this one area that browsers may vary). Matching the path (assuming the domain matches) is a simple matter that the requested path must be inside the path specified on the cookie. Typically session cookies are set with path=/ or path=/applicationName/ so the cookie is available to all requests into the application.
__Response to Added:__
Will a cookie for .example.com be available for www.example.com? Yes
Will a cookie for .example.com be available for example.com? Don't Know
Will a cookie for example.com be available for www.example.com? Shouldn't but... *
Will a cookie for example.com be available for anotherexample.com? No
Will www.example.com be able to set cookie for example.com? Yes
Will www.example.com be able to set cookie for www2.example.com? No (Except via .example.com)
Will www.example.com be able to set cookie for .com? No (Can't set a cookie this high up the namespace nor can you set one for something like .co.uk).
* I'm unable to test this right now but I have an inkling that at least IE7/6 would treat the path example.com as if it were .example.com.
The last (third to be exactly) RFC for this issue is RFC-6265 (Obsoletes RFC-2965 that in turn obsoletes RFC-2109).
According to it if the server omits the Domain attribute, the user agent will return the cookie only to the origin server (the server on which a given resource resides). But it's also warning that some existing user agents treat an absent Domain attribute as if the Domain attribute were present and contained the current host name (For example, if example.com returns a Set-Cookie header without a Domain attribute, these user agents will erroneously send the cookie to www.example.com as well).
When the Domain attribute have been specified, it will be treated as complete domain name (if there is the leading dot in attribute it will be ignored). Server should match the domain specified in attribute (have exactly the same domain name or to be a subdomain of it) to get this cookie. More accurately it specified here.
So, for example:
cookie attribute Domain=.example.com is equivalent to Domain=example.com
cookies with such Domain attributes will be available for example.com and www.example.com
cookies with such Domain attributes will be not available for another-example.com
specifying cookie attribute like Domain=www.example.com will close the way for www4.example.com
PS: trailing comma in Domain attribute will cause the user agent to ignore the attribute =(
The RFCs are known not to reflect reality.
Better check draft-ietf-httpstate-cookie, work in progress.
There are rules that determine whether a browser will accept the Set-header response header (server-side cookie writing), a slightly different rules/interpretations for cookie set using Javascript (I haven't tested VBScript).
Then there are rules that determine whether the browser will send a cookie along with the page request.
There are differences between the major browser engines how domain matches are handled, and how parameters in path values are interpreted. You can find some empirical evidence in the article How Different Browsers Handle Cookies Differently
Will www.example.com be able to set cookie for .com?
No, but example.com.fr may be able to set a cookie for example2.com.fr. Firefox protects against this by maintaining a list of TLDs: http://securitylabs.websense.com/content/Blogs/3108.aspx
Apparently Internet Explorer doesn't allow two-letter domains to set cookies, which I suppose explains why o2.ie simply redirects to o2online.ie. I'd often wondered that.
I was surprised to read section 3.3.2 about rejecting cookies:
https://www.rfc-editor.org/rfc/rfc2965
That says that a browser should reject a cookie from x.y.z.com with domain .z.com, because 'x.y' contains a dot. So, unless I am misinterpreting the RFC and/or the questions above, there could be questions added:
Will a cookie for .example.com be available for www.yyy.example.com? No.
Will a cookie set by origin server www.yyy.example.com, with domain .example.com, have it's value sent by the user agent to xxx.example.com? No.
I need to set a cookie from my main domain, read then remove the cookie from a subdomain. But I also need to possibly set that cookie again on the domain in the future, and read it later on the subdomain. Basically, a stream of one-way communication. I cannot have the main domain handle unsetting the cookie, because it could be months between users hitting the main domain and the subdomain.
I set a cookie on my domain, like so:
document.cookie = "mycookie=testcookie;domain=example.com;max-age=31536000;";
I access it just fine on another subdomain, as such:
document.cookie.replace(/(?:(?:^|.*;\s*)testcookie\s*\=\s*([^;]*).*$)|^.*$/, "$1");
I then try to kill it from the subdomain:
document.cookie = "mycookie=;domain=example.com;max-age=0;";
That does not work. Cookie is still set.
However, setting it like this clears it:
document.cookie = "mycookie=;domain=example.com;max-age=31536000;";
It now returns "" when asking for it from the subdomain.
But... if I go back to the domain and set it again, and I can see it has been set, the subdomain still returns ""
Is there some sort of... hierarchy of cookies I'm missing? I'm unsure how this behaves or how to overcome this.
In order to enable this you have to place a period . before the root domain, like so: .example.com This is important because of the way the cookie standardization is setup. This format should be compatible with most modern browsers.
In addition, the path must be identical when accessing or modifying the cookie across different subdomains. The easiest way to do this is to just use the root path for the domain, /. For example, if you set the cookie from sub1.example.com/page1 and try to access it from sub2.example.com/page2, even though you set the domain as .example.com you also have to set the path=/ in order to access it and modify it from any path on other subdomains.
Ultimately:
document.cookie = "mycookie=testcookie;domain=.example.com;path=/;max-age=31536000";
will enable you to set it and
document.cookie = "mycookie=;domain=.example.com;path=/;max-age=0";
will let you delete it.
I can't access any cookie from JavaScript. I need to read some value and send them via JSON for my custom checks.
I've tried to access cookies from JS, like it was described at:
http://www.w3schools.com/js/js_cookies.asp
Get cookie by name
As you can see at the code, it's seen as clear as a crystal the next:
var c_value = document.cookie;
When I'm trying to access the document.cookie value from the Chrome's web-debugger, I see only the empty string at the Watch expressions:
So I can't read cookies value, which I need.
I've checked the cookie name, which I'm sending to get an associated value IS correct.
Also, I'm using the W3Schools source code for getting cookies, if you're interested (but from the 2nd link, the technique is similar).
How can I fix my issue?
You are most likely dealing with httponly cookies. httponly is a flag you can set on cookies meaning they can not be accessed by JavaScript. This is to prevent malicious scripts stealing cookies with sensitive data or even entire sessions.
So you either have to disable the httponly flag or you need to find another way to get the data to your javascript.
By looking at your code it should be easy to disable the http only flag:
Response.AddHeader("Set-Cookie", "CookieName=CookieValue; path=/;");
Response.SetCookie(new HttpCookie("session-id") { Value = Guid.NewGuid().ToString(), HttpOnly = false });
Response.SetCookie(new HttpCookie("user-name") { Value = data.Login, HttpOnly = false });
Now you should be able to access the cookie information from JavaScript. However I don't know exactly what kind of data you are trying to get so maybe you can go for another approach instead and for example render some data attribute on the page with the information you need instead of trying to read the cookie:
<div id="example" data-info="whatever data you are trying to retrieve"></div>
console.log(document.getElementById('example').getAttribute('data-info'));
keep an eye also to the cookie's Path attribute, as the cookie is only visible to subdirectories under Path. I had your issue and I solved setting Path "/"
I would say http only is your first culprit but this can also occur by not setting the scope of your cookie.
If the site has been redirected from another domain, you will need to look into setting the scope of the cookie. Domain and Path defines the scope of the cookie, which URLs the cookie should be sent to. Depending on this, you might not see the cookie in your response.
I ran across this issue when setting a cookie on a successful SAML SSO login and couldn't retrieve the cookie from the Document because it was never send as part of the request.
I had the same problem several times. And every time, it was for a different reason.
Different reasons:
problem of httpOnly field. It was set to false and I was trying to access it from the console. Setting it to true or accessing it from the source code did the trick.
problem of secure field. It was true and I was using only http.
problem of Expires / Max-Age. The cookie was outdated and it was not visible in document.cookie.
If your cookie is set as Set-Cookie or Set-Cookie2 it's not part of the response headers collection: http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders%28%29-method
Returns all headers from the response, with the exception of those whose field name is Set-Cookie or Set-Cookie2.
If you are using some secure authentication then that case you could not access cookies directly because of secure. you have to change some response attribute in server side using below code .
Response.AddHeader("Set-Cookie", "CookieName=CookieValue; path=/;");
Response.SetCookie(new HttpCookie("session-id") { Value = Guid.NewGuid().ToString(), HttpOnly = false });
Response.SetCookie(new HttpCookie("user-name") { Value = data.Login, HttpOnly = false });
But you should not because it may change secure to un-secure, so you have to find out solution that be done in server side to delete cookies and allow to you do some operations.
Its possible to do changes in server side.
I tried it with jQuery:
$.cookie('test', 'value', { expires: 7, path: '/', domain: 'test.com' });
but it won't work.
it's possible to do?
Nope, that will not work for security reasons.
It is not possible to do due to security reasons.
if you are in control of the 2nd domain there are some options to share your cookies described already here:
What's your favorite cross domain cookie sharing approach?
Due to many people abusing it, most browsers block 3rd party either by default or by the user setting such a preference.
From Cookies:
Each cookie also has a domain and a
path. The domain tells the browser to
which domain the cookie should be
sent. If you don't specify it, it
becomes the domain of the page that
sets the cookie, in the case of this
page www.quirksmode.org. Please note
that the purpose of the domain is to
allow cookies to cross sub-domains. My
cookie will not be read by
search.quirksmode.org because its
domain is www.quirksmode.org . When I
set the domain to quirksmode.org, the
search sub-domain may also read the
cookie.
I cannot set the cookie domain to a domain I'm not in, I cannot make the
domain www.microsoft.com . Only
quirksmode.org is allowed, in this
case.
when i save cookie, it stored with the current URL link., also when i get cookie that search for the current URL only. i need to save and retrieve cookies with my own defined URL links. can you help me
You cannot read cookies set by different domains. That would be a horrific security problem if it was possible.