Skip to content

Issues with the new Cookie management #11208

@stefanozoffoli

Description

@stefanozoffoli

This is a (multiple allowed):

  • bug

  • enhancement

  • feature-discussion (RFC)

  • CakePHP Version: 3.5.2

  • Platform and Target: Apache/2.4.12 (Win32) OpenSSL/1.0.1l PHP/5.6.8

What you did

I tried to port my previous "remember me" cookie implementation (based on Cookie Component) to the new Cookie management.

My codebase is pretty simple:

$this->response = $this->response->withCookie(
    (new Cookie('urmc'))
        ->withValue([
            'user_id' => $user_id,
            'token' => $token,
        ])
        ->withExpiry(new DateTime('+1 month'))
        ->withHttpOnly(true)
);

return $this->redirect('/');

I had 3 problems:

Cookie with redirect

If I set the cookie before a redirect, it doesn't set any cookie.
I tried to debug ResponseEmitter.php: in the function emitHeaders() it seems to resets the value of the variable $cookies right after setting a header of type 'Location: ...'.
For debug purpose I tried to temporarily remove the redirect like this:

foreach ($response->getHeaders() as $name => $values) {
    if (strtolower($name) === 'set-cookie') {
        $cookies = array_merge($cookies, $values);
        continue;
    }
    if (strtolower($name) === 'location') {
        continue;
    }
    ...

and then $cookies correctly had the cookie i setted.

Cookie with value of type array

After I removed the redirect, it gave me another error:

setcookie() expects parameter 2 to be string, array given

This is because it calls Response->convertCookieToArray() that doesn't convert values of type array to string.
But I saw that Cookie() object can handle values of type array by using an internal variable $isExpanded... is this correct?
I expected that I could set a cookie with value of type array without the need to explicitly call json_encode()

Encrypted Cookie

I don't know if I'm using it incorrectly, but EncryptedCookieMiddleware only decodes my cookie and doesn't encode it.
This is my code (in routes.php):

Router::scope('/', function (RouteBuilder $routes) {
    ...

    $routes->registerMiddleware('csrf', new CsrfProtectionMiddleware());
    $routes->registerMiddleware('cookies', new EncryptedCookieMiddleware(['urmc'], Configure::read('Security.cookieKey')));

    $routes->applyMiddleware('csrf', 'cookies');

    ...

    $routes->fallbacks(DashedRoute::class);
});

Maybe I didn't understand really well how middleware works, but there is only a __invoke() function that calls both decodeCookies() in the request and encodeCookies() in the response...
But I set the cookie after that, right? So the cookie doesn't encode because the __invoke() function has already been called?

Thank you

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions