I recently ran into a problem where I had a suite of applications hosted on a set of subdomains that all needed to be able to share a single cookie. Any cookies other than the shared cookie needed to stay specific to their subdomain, but this one shared cookie needed to be accessible to any of them. I also wanted to accomplish this using Laravel's Cookie
facade.
To accomplish this, there were two issues to solve.
- All cookies created by the Laravel framework are encrypted by default. (link)
- I needed to figure out how to set a domain on the shared cookie that was different than the domain it was being set from.
In Laravel 5.1, a feature was added which allows you to add a list of cookie names that should not be encrypted to the EncryptCookies
Middleware under the $except
array. Check out the docs for information on how to accomplish this.
In my EncryptCookies
Middleware, I changed the $except
array to include my cookie name.
protected $except = [
'shared_cookie'
];
After reading an article discussing the issue of sharing cookies across subdomains, I realized that I needed to create the shared cookie with a domain that was different from the default value. The default domain value for all cookies is the domain your site is located at. If your site was subdomain.example.com
all cookies by default would be set for that domain. In order to share a cookie across subdomains however, a cookie needs to be created with a domain of .example.com
. Notice the leading .
in the domain of the cookie. This is important. By setting the domain as such, any subdomain will be able to access this cookie as it's own.
There is a domain
setting in config/session.php
that will allow you to change the default domain that cookies are set from, but I wanted to maintain this default, and only override the behavior for the one shared cookie. To accomplish this, I had to dig into the CookieJar
class of Laravel and see exactly how these cookies were being created.
Come to find out, the make
method of the CookieJar
class accepts a list of arguments that includes a spot for a domain. The default is used if a null
value is passed in for the domain, but we can easily pass in our own domain.
$num_of_minutes_until_expire = 60 * 24 * 7; // one week
Cookie::queue('shared_cookie', 'my_shared_value', $num_of_minutes_until_expire, null, '.example.com');
This will send a cookie along with our next response which will not be encrypted (thanks to EncryptCookies
), and will have a domain of .example.com
which will allow us to access it from any subdomains.
Thanks! That's the cool tip!