Start building
Updates

Setting Cookies to Subdomains in JavaScript

Bartosz Olchówka, Dec 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).

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.

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.


Latest articles

Oct 8, 2024

What is Syntax? How Syntax Shapes Programming Languages

Sep 11, 2024

What is JavaScript? Key Concepts and Uses Explained

Sep 3, 2024

What is Dynamic Programming? Understanding the Basics