Set Shared Cookies Across Subdomains on localhost

If you are running multiple apps on localhost across different subdomains (foo.localhost, bar.localhost, etc.) and want to set a cookie on one domain that is accessible from another subdomain, then you will have to watch out for a couple of things.

Setting a Cookie with Domain=.localhost or Domain=localhost (since the dot notation is deprecated) will not share it across subdomains like foo.localhost, bar.localhost or foo.bar.localhost on Chrome and Firefox. It seems to work on Safari today but not sure about the future.

Generally, user agents (like browsers) do not allow setting cookies on top-level domains like .com (Domain=com), .net (Domain=net) or any other public suffixes and maybe that is the reason why Chrome and Firefox ignore setting cookies for Domain=localhost. To clarify, the cookie will/can be set for the localhost origin but not for its subdomains.

If you didn’t know, Domain=example.com sets the cookie not only for example.com but also for all its subdomains like foo.example.com, bar.example.com, foo.bar.example.com and so on. Hence, some of you might expect Domain=localhost to do the same for its subdomains but as mentioned above, most browsers/user agents will ignore that.

The actual reason why Domain=localhost kind of gets ignored or dropped by most user agents is not documented anywhere but some StackOverflow threads talk about how the domain value must have two or more dots (which localhost does not) but I am not sure if that is correct.

Personally, I think that if an app running on say localhost:3000 or app1.localhost was allowed to set a cookie with Domain=localhost, then another app for a different project or client running on localhost:4000 or app2.localhost would unintendedly start receiving the same cookie in its HTTP requests. Maybe user agents want to avoid that.

RFC 6265 also talks about the security concerns around why user agents won’t allow setting cookies on top-level domains. For instance, Domain=com is not allowed due to the following reason:

For security reasons, many user agents are configured to reject Domain attributes that correspond to “public suffixes”. For example, some user agents will reject Domain attributes of “com” or “co.uk”.



This step is essential for preventing attacker.com from disrupting the integrity of example.com by setting a cookie with a Domain attribute of “com”.

Solution

It makes sense to use a higher level (sub) domain on localhost for your web apps and use that to set cookies across subdomains.

For example, we can run our apps on domain names like http://foo.project1.localhost and http://bar.project1.localhost. Now if our app sets HTTP cookies for Domain=project1.localhost from any of these three domains, then the user agents will respect them and send them as Cookie headers in the requests to all these hosts. It would even work for deeper level hosts like foo.bar.project1.localhost.

Do remember that cookies for a domain are valid (sent in request headers) for its higher-level (sub) domains too. foo.example.com can set cookies for example.com (but not vice-versa) using Domain=example.com which works for example.com, foo.example.com and foo.bar.example.com.

This solution will work across all major browsers like Chrome, Safari, Firefox, Edge, etc. Do note that you may have to add the different subdomains (subdomain.localhost) to /etc/hosts for Safari though. I hope this changes in the future.

Another solution is to avoid using localhost altogether and have other custom local domains like foo.example.com or foo.example.local with appropriate entries in /etc/hosts. But if you can make things work with localhost itself then why not.

Leave a Reply

Your email address will not be published. Required fields are marked *