Sharing Laravel Cookies across subdomains
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
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.
Setting Non-Encrypted Cookies
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.
EncryptCookies Middleware, I changed the
$except array to include my cookie name.
protected $except = [ 'shared_cookie' ];
Setting a Custom Domain
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.