Laravel shared cookie detection issue in domain and subdomain Laravel shared cookie detection issue in domain and subdomain laravel laravel

Laravel shared cookie detection issue in domain and subdomain


You need to implement your own "retrieving" and "setting" a cookie.

Retrieving (has, get) cookies

Create yourself new class (anywhere you like, but I would do app/Foundation/Facades/) with name Cookie.

use \Illuminate\Support\Facades\Cookie as CookieStock;class Cookie extends CookieStock {     //implement your own has(...);    public static function has($key)    {        return ! is_null(static::$app['request']->cookie(PREFIX . $key, null)); //get the prefix from .env file for your case APP_ENV    }    //implement your own get(...);    public static function get($key = null, $default = null) {...}}

Now open up config/app.php and change corresponding alias (cookie).

Setting (make) cookies

Create yourself new provider (use artisan), and copy-paste code from Illuminate\Cookie\CookieServiceProvider.php and change namespaces.Again open up config/app.php and change corresponding service provider with the new one.

Create yourself new class (anywhere you like, but I would do app/Foundation/Cookie/) with name CookieJar.

use \Illuminate\Cookie\CookieJar as CookieJarStock;class CookieJar extends CookieJarStock {//Override any method you think is relevant (my guess is make(), I am not sure at the moment about queue related methods)    public function make($name, $value, $minutes = 0, $path = null, $domain = null, $secure = false, $httpOnly = true)    {        // check before applying the PREFIX        if (!empty($name)) {            $name = PREFIX . $name; // get the PREFIX same way as before        }        return parent::make($name, $value, $minutes, $path, $domain, $secure, $httpOnly);    }}

Update the code in your own cookie service provider to use your implementation of CookieJar (line 19).

Run $ composer dump-autoload, and you should be done.

Update

Since BorisD.Teoharov brought up, that if framework changes signature of CookieJarStocks make() (or any other cookie related function) in between the major versions, I made a example repository, that includes a test that can be used as is and it will fail if signature change happens.

It is as simple as this:

public function test_custom_cookie_jar_can_be_resolved(){    resolve(\App\Foundation\Cookie\CookieJar::class);    $this->assertTrue(true);}

Detailed how to can be inspected in the corresponding commit diff.


I've setup test environments to make sure, I'm not missing any details.

As in my former answer, I thought invalidating cookies will be sufficient for that case, but as @BorisD suggested it is not, and I've confirmed that on my tests.

So there are a few important notes, coming from my experiences...

  1. Don't mix Laravel versions in subdomains - If using SESSION_DOMAIN you need to make sure your Laravel version matches (between root and subdomains), cause I've experimented with 5.4 under example.com domain and 5.6 under dev.example.com. This showed me some inconsistency in dealing with Cookies, so some important changes have been done, between these versions, and you can be sure it will not work correctly if you mix versions. I finally ended up with Laravel 5.6 on both domains, so I'm not 100% sure if that works on Laravel 5.4, but I think it should.

  2. Make sure all your subdomains use the same APP_KEY - otherwise, Laravel will be unable to decrypt the Cookie, returning null value, cause all encryption/decryption in Laravel uses this app key...

  3. SESSION_DOMAIN. In SESSION_DOMAIN I've pointed the same root domain like example.com for both domains. With this setting, I can create a cookie on root domain, and retrieve it correctly on both domains. After that setting, creating a cookie on subdomain forces root domain to receive new value from subdomains cookie also, and they are overridden. So I guess everything works here as requested in the original question.

  4. Cookie make parameters - In case you want to use a subdomain in SESSION_DOMAIN, you can safely do that also. However, you need to make sure, important let's call them global cookies are defined in a bit different way. Cookie make syntax:

    Cookie make(string $name, string $value, int $minutes, string $path = null, string $domain = null, bool $secure = false, bool $httpOnly = true)

    So what's important here, you need to put your root domain for this particular cookie on creation like this for example:return response($content)->cookie('name','value',10,null,'example.com')

Conclusions:

  1. With this config, you should be able to access your Cookies properly under subdomains and your root domain.
  2. You may probably need to update your Laravel installations to 5.6, which will force you to upgrade to PHP 7.1 at least (there were some changes to cookies in php also)
  3. And finally, in your code, don't rely on Cookie existence, but on its values only (I don't know if that's in your case).


You could set a prefix for the cookie name depending on the environment.

First, add COOKIE_PREFIX to your env file.

COOKIE_PREFIX=dev

Then, use it when setting your cookie

$cookie = cookie(env('COOKIE_PREFIX', 'prod') . '_name', 'value', $minutes);

Then, retrieve it like so

$value = $request->cookie(env('COOKIE_PREFIX', 'prod') . '_name');