in Platform Updates

Setting Cookies to Subdomains in JavaScript

Bartosz Olchówka in Programming, on December 17, 2014

Setting cookies to subdomains can be very tricky. We’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, we had to determine the target domain (the actual value of ”.mycompany.com”) automatically because our 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 us determine if we can set a cookie to .co.uk (which we can’t) or .bar.com (which we 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 our 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.

See other Platform Updates

How Tissot Watch Notifies About a Weak Battery

Watches usually don’t have a digital display which shows a battery status icon.

Read more

What is SPF - Sender Policy Framework

Spoofing is a type of a computer attack in which the attacker pretends to be someone else.

Read more
See all updates