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 preventingattacker.com
from disrupting the integrity ofexample.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.