Setting cookies to subdomains can be very tricky.
I've recently faced a problem of setting a cookie from foo.mycompany.com to all subdomains in a *.mycompany.com
domain. The solution seemed pretty straightforward: just set a wildcard cookie to .mycompany.com
(note that the first character is a dot). However, I had to determine the target domain (the actual value of ”.mycompany.com
”) automatically because my code is fired on tens of thousands of different domains.
And here came the problem: the list of Top-Level Domains.
Top-Level Domains and cookies
Let’s consider two similar domains:
- foo.bar.com
- foo.co.uk
JavaScript allows you to set a cookie available to all bar.com
subdomains from within the foo.bar.com
subdomain.
However, it won’t let you set a cookie to all co.uk
subdomains from within the foo.co.ok
subdomain because co.uk
is a Top-Level Domain. If it was possible, your browser would send that cookie to all websites available in the British (co.uk
) domain.
Web browsers don’t offer a way to check if the given string is a Top-Level Domain or not. If such a feature existed, it would help me determine if I can set a cookie to .co.uk
(which I can’t) or .bar.com
(which I can).
List of TLDs in your app (not recommended)
One of the solutions is to store a list of all Top-Level Domains in your app and check your domain against this list. Mozilla Foundation hosts a project called Public Suffix List which stores all TLD names in one place.
But in reality, keeping the list in your app is just a pain in the ass.
The “try and check” method (recommended)
There’s an easier solution though: just set a cookie to the domain and check if the browser actually set that cookie. If it didn’t, it’s a Top-Level Domain and we need to try setting a cookie to a subdomain.
Here’s a working example of the code that sets the cookie and copes with the mentioned TLD problem. It’s a modification of the renowned code snippet from an article about cookies on QuirksMode:
var Cookie = { set: function(name, value, days) { var domain, domainParts, date, expires, host; if (days) { date = new Date(); date.setTime(date.getTime()+(days*24*60*60*1000)); expires = "; expires="+date.toGMTString(); } else { expires = ""; } host = location.host; if (host.split('.').length === 1) { // no "." in a domain - it's localhost or something similar document.cookie = name+"="+value+expires+"; path=/"; } else { // Remember the cookie on all subdomains. // // Start with trying to set cookie to the top domain. // (example: if user is on foo.com, try to set // cookie to domain ".com") // // If the cookie will not be set, it means ".com" // is a top level domain and we need to // set the cookie to ".foo.com" domainParts = host.split('.'); domainParts.shift(); domain = '.'+domainParts.join('.'); document.cookie = name+"="+value+expires+"; path=/; domain="+domain; // check if cookie was successfuly set to the given domain // (otherwise it was a Top-Level Domain) if (Cookie.get(name) == null || Cookie.get(name) != value) { // append "." to current domain domain = '.'+host; document.cookie = name+"="+value+expires+"; path=/; domain="+domain; } } }, get: function(name) { var nameEQ = name + "="; var ca = document.cookie.split(';'); for (var i=0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0)==' ') { c = c.substring(1,c.length); } if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); } return null; }, erase: function(name) { Cookie.set(name, '', -1); } };
And here’s how to use it:
Cookie.set('test', '123');
When we are on foo.bar.com
domain, the cookie will be available on *.bar.com
subdomains.
But when we are on foo.co.uk
domain, the cookie will be available on *.foo.co.uk
subdomains.
This code works fine on my production environment on thousands of different domains. It’s way easier than storing the list of Top-Level Domains and comparing the current domain to the ones on the list.
Top comments (0)