2

In Craft 2, we could set a cookie like this...

craft()->userSession->saveCookie()

... and that would make it a state cookie. This thread describes it pretty well. Essentially, you would end up with a cookie whose name began with a hashed string.

b72b7553c36d6600e9aeb6c40513deb8MyCookie

However, it seems like that behavior has been largely removed in Craft 3. When I try to save a cookie now, I do it more like this...

$cookie = new Cookie();
$cookie->name = $cookieName;
$cookie->value = $cookieValue;
$cookie->expire = time() + $lifespan;
Craft::$app->getResponse()->getCookies()->add($cookie);

... which doesn't create a state cookie. The cookie name is very simple.

MyCookie

Generally speaking, that doesn't bother me. But I worry about compatibility issues with the Craft 2 version of my plugin. It's somewhat important that cookies from the old system are recognized when Craft is upgraded.

What is the solution for this? How do I ensure that my old cookies are recognized properly, and/or continue saving this data using the original hashed format?

2

After a lot of trial & error, it turns out this is not possible. (At least, not by me.)

I was able to retrieve the raw Craft 2 cookie data using the following code...

// Generate hash of Craft 2 cookie
private function _getCraft2CookieHash()
{
    $newBasePath = Craft::$app->getBasePath();
    $oldBasePath = str_replace('vendor/craftcms/cms/src', 'app', $newBasePath);
    $appId = sprintf('%x',crc32($oldBasePath.'Craft'));
    return md5('Yii.Craft\UserSessionService.'.$appId);
}

// Get existing Craft 2 cookie data
public function getExistingCookieData()
{
    // Get name of Craft 2 cookie
    $craft2CookieHash = $this->_getCraft2CookieHash();
    $craft2CookieName = $craft2CookieHash.'MyCookie';

    // If Craft 2 cookie exists
    if (isset($_COOKIE[$craft2CookieName])) {

        // Get value of Craft 2 cookie
        $cookieValue = $_COOKIE[$craft2CookieName];

        /**
         * THIS IS WHERE IT ALL FELL APART
         * The cookie data is too highly encoded.
         */

    }
}

I was able to correctly determine the hash which makes up part of the Craft 2 cookie's name. Keep in mind, this only works if the site's folder structure did not change. The docs give you two different ways to upgrade the site from Craft 2, and this hash-detection logic will only work if you choose to "keep your current directory structure".

However, things really fell apart when trying to get the actual data from the cookie. The data is encoded in some very complex ways. In Craft 2, it uses a complicated function called computeHMAC which goes way beyond my understanding of security. There is no equivalent function in Craft 3 (and if there was, it would probably operate quite differently).

Sadly, I have to throw in the towel and admit defeat here. Backwards engineering the computeHMAC function is more than my puny brain can handle. :(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.