Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cookie with string type field expire #19917

Closed
hukimato opened this issue Jul 27, 2023 · 9 comments
Closed

Cookie with string type field expire #19917

hukimato opened this issue Jul 27, 2023 · 9 comments

Comments

@hukimato
Copy link

I made request to auth service and got cookie from it.
I supposed to set this cookie to client:

Yii::$app->response->cookies->add($response->cookies->get('cookie_name'));
But this code will generate exception.

yii\base\ErrorException: setcookie() expects parameter 3 to be integer, string given in /vagrant/libs/vendor/php_7.2/vendor/yiisoft/yii2/web/Response.php:427

I found out, that cookie returned by get method returned object with string type of expire value:

  object(yii\web\Cookie)#88 (8) {
   ["name"]=> string(5) "cookie_name"
   ["value"]=> string(27) "value"
   ["domain"]=> string(7) ".my.domain"
   ["expire"]=> string(29) "Sat, 27 Jan 2024 11:39:10 GMT"
   ["path"]=> string(1) "/"
   ["secure"]=> bool(true)
   ["httpOnly"]=> bool(true)
   ["sameSite"]=> string(3) "Lax"
}

Of course it was easily fixed by

$cookie = $response->cookies->get('cookie_name');
$cookie->expire = strtotime($cookie->expire);

But class Cookie has phpdoc comment, that type of this field supposed to be integer.

Yii version 2.0.4
PHP version php7.2-fpm
Operating system Ubuntu 20.04.6 LTS Linux 5.4.0-155-generic x86_64

@rhertogh
Copy link
Contributor

@hukimato

I made request to auth service and got cookie from it.

Could you please clarify what you mean with that?

@hukimato
Copy link
Author

hukimato commented Jul 27, 2023

@rhertogh

I wrote this for a better understanding of the code I wrote. To not reveal the name of cookie, I use cookie_name.

So, first of all, Clients have cookie, with name cookie_name, which helps us to classify users by subscription type.
To get actual information about subscription, we make request to auth-service. It returns new auth cookie in case user changed his subscription type, or returns the same one. Cookie returned in Set-Cookie header, but colleague told me, I can get it like this $response->cookies->get('cookie_name').
$response - response from auth service.

I hope, this is enough, but I think this is not about the case.

This case is about Cookie object initialization, where expire value is set with string, not with timestamp.

@bizley
Copy link
Member

bizley commented Jul 28, 2023

I wonder how this happens since PHP should change the time string to unix timestamp internally...

@rhertogh
Copy link
Contributor

@hukimato

Thanks for the explanation, but for me it's still unclear what "auth service" is? And where $response comes from, is it for example a \yii\httpclient\Response or \yii\web\Response?

@hukimato
Copy link
Author

It is \yii\httpclient\Response

$client = new \yii\httpclient\Client();
$response = $client->createRequest()
    ->setMethod('GET')
    ->setUrl("http://_some_url_?cookie_name=" . Yii::$app->request->cookies->getValue('cookie_name'))
    ->send();

if ($response->isOk){
    Yii::$app->response->cookies->add($response->cookies->get('cookie_name'));
    ...

@rhertogh
Copy link
Contributor

@bizley

I wonder how this happens since PHP should change the time string to unix timestamp internally...

Looks like PHP behaves the opposite, from the docs:

You may notice the expires_or_options parameter takes on a Unix timestamp, as opposed to the date format Wdy, DD-Mon-YYYY HH:MM:SS GMT, this is because PHP does this conversion internally

@rhertogh
Copy link
Contributor

@hukimato
Thanks. I've located the issue, \yii\httpclient\Response::parseCookie() does indeed set the 'expire' as a string (it only converts 'expires' to 'expire' but there is no type casting).

@rhertogh
Copy link
Contributor

Things get even more weird:

echo setcookie('test', 'value', 'Sat, 27 Jan 2024 11:39:10 GMT') ? 'y' : 'n';
PHP Version Result
5.6.40 Warning: setcookie() expects parameter 3 to be long, string given in /home/user/scripts/code.php on line 2
7.2.34 Warning: setcookie() expects parameter 3 to be integer, string given in /home/user/scripts/code.php on line 2
7.4.33 y (seems to work)
8.1.19 Fatal error: Uncaught TypeError: setcookie(): Argument #3 ($expires_or_options) must be of type array

@bizley So your statement that it's automatically converted is correct when using PHP 7.4

@rhertogh
Copy link
Contributor

PR that broadens the accepted types for Cookie::$expire from int to int|string|null: #19920

@bizley bizley closed this as completed Aug 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants