Will Browning.

26th Oct 18 #laravel 3 min read

Sharing Cookies with Subdomains in Laravel

Sometimes it can be useful for a subdomain such as app.example.com to have access to the cookies that are set by example.com. A situation where this could be used would be for a very simple referral tracking system, where example.com sets a cookie if there is a query string present in the URL. Then when the user registers on app.example.com this cookie is retrieved and the data regarding who referred that user is stored in the database.

Setting up Our Example Sites

For this example I'll be using Laravel Homestead to set up a couple of local Laravel sites.

laravel new example && laravel new subdomain

Then we need to edit Homestead.yaml and our hosts file to add addresses for these applications.

sites:
    - map: example.test
      to: /home/vagrant/code/example/public/
    - map: app.example.test
      to: /home/vagrant/code/subdomain/public/
192.168.10.10 example.test
192.168.10.10 app.example.test
homestead up --provision

When you've provisioned Homestead you should see the new Laravel welcome screen when you visit example.test and app.example.test.

New Laravel App

Updating our Environment Variables

Let's edit our .env file for our main example.test site. Update the following values.

APP_URL=http://example.test
SESSION_DOMAIN=.example.test

The SESSION_DOMAIN variable is important as this will allow our subdomain to access all cookies set by the parent domain.

Now let's also update the .env file for our app.example.test site.

APP_URL=http://app.example.test

We don't need to set SESSION_DOMAIN here.

We've left SESSION_DRIVER as the default value which is file for both sites.

In our main example.test code update the default welcome route in web.php.

Route::get('/', function () {
    Cookie::queue(Cookie::make('test', 'abc', 60));

    return view('welcome');
});

Route::get('/cookie', function () {
    return Cookie::get('test');
});

Here we're informing Laravel to set a Cookie named 'test' with a value of 'abc' that will expire in 60 minutes.

First visit example.test in your browser, then if you visit example.test/cookie you should see the value we set of abc. So we know that our Cookie has been succesfully set.

If you head over to your app.example.test code and add the following to the web.php routes file:

Route::get('/cookie', function () {
    return Cookie::get('test');
});

Then visit app.example.test/cookie you won't be able to see anything yet as Laravel by default encrypts all cookies that are set.

There are a couple of options we have here on how to access the cookie.

  1. Use the same APP_KEY value for both sites

We can copy the APP_KEY value from our example.test .env file and paste it in our app.example.test .env file so that they both have the same value. If you try this and then visit again app.example.test/cookie you will be able to see the value abc and the cookie can be decrypted succsesfully.

The reason this works is because Laravel uses our APP_KEY value when encrypting, decrypting and signing data.

Some people may feel uncomfortable having the same APP_KEY value for both sites but there is another way.

  1. Disable encryption for the cookie in question

We can tell Laravel not to encrypt certain cookies if they do not contain sensitive data.

In both of our sites open up the app/Http/Middleware folder and edit the EncryptCookies.php file.

protected $except = [
    'test'
];

Here we can add the name of any cookies we don't wish to be encrypted. Make sure you've added this to both sites.

Change the value of the cookie set by example.test to something else so we can be sure it's working.

Cookie::queue(Cookie::make('test', '123', 60));

Then visit example.test in your browser again. Check example.test/cookie and you should see the value of '123' this time.

Now if you visit app.example.test/cookie you should be able to access the cookie and see the value of '123' returned.

You should only disable encryption for a cookie if it contains non-sensitive information.

Sharing Cookies for a Simple Referral System

I'll write another post shortly detailing how we can use what we've applied here to create a very simple referral system that tracks who has been referred by who. The system will use middleware to determine whether to set a cookie if a certain query string is present in the request. This will enable you to link to any url on your main site like so example.test/?ref=referral-id or example.test/pricing?ref=referral-id.

Update: You can find the simple referral system post here - Building a Simple Referral System in Laravel

Like what you've seen here?

Fire over your email and I'll keep you updated once a month about any new posts. No Spam.