From: Roeland Jago Douma Date: Fri, 19 Jun 2020 07:31:47 +0000 (+0200) Subject: Allow to specify the cookie type for appframework responses X-Git-Tag: v20.0.0beta1~383^2 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=fbf9772a3eafeab74cc5b3f76e7ad7cc081991bb;p=nextcloud-server.git Allow to specify the cookie type for appframework responses In general it is good to set them to Lax. But also to give devs more control over them is not a bad thing. Helps with #21474 Signed-off-by: Roeland Jago Douma --- diff --git a/lib/private/AppFramework/App.php b/lib/private/AppFramework/App.php index e02f372e41c..ea97ea4096d 100644 --- a/lib/private/AppFramework/App.php +++ b/lib/private/AppFramework/App.php @@ -151,6 +151,8 @@ class App { if ($value['expireDate'] instanceof \DateTime) { $expireDate = $value['expireDate']->getTimestamp(); } + $sameSite = $value['sameSite'] ?? 'Lax'; + $io->setCookie( $name, $value['value'], @@ -158,7 +160,8 @@ class App { $container->getServer()->getWebRoot(), null, $container->getServer()->getRequest()->getServerProtocol() === 'https', - true + true, + $sameSite ); } diff --git a/lib/private/AppFramework/Http/Output.php b/lib/private/AppFramework/Http/Output.php index fd95f370360..8777c1970a6 100644 --- a/lib/private/AppFramework/Http/Output.php +++ b/lib/private/AppFramework/Http/Output.php @@ -92,8 +92,20 @@ class Output implements IOutput { * @param bool $secure * @param bool $httpOnly */ - public function setCookie($name, $value, $expire, $path, $domain, $secure, $httpOnly) { + public function setCookie($name, $value, $expire, $path, $domain, $secure, $httpOnly, $sameSite = 'Lax') { $path = $this->webRoot ? : '/'; - setcookie($name, $value, $expire, $path, $domain, $secure, $httpOnly); + + if (PHP_VERSION_ID < 70300) { + setcookie($name, $value, $expire, $path, $domain, $secure, $httpOnly); + } else { + setcookie($name, $value, [ + 'expires' => $expire, + 'path' => $path, + 'domain' => $domain, + 'secure' => $secure, + 'httponly' => $httpOnly, + 'samesite' => $sameSite + ]); + } } } diff --git a/lib/public/AppFramework/Http/IOutput.php b/lib/public/AppFramework/Http/IOutput.php index 888c9f45b23..39543dc9bf1 100644 --- a/lib/public/AppFramework/Http/IOutput.php +++ b/lib/public/AppFramework/Http/IOutput.php @@ -72,7 +72,8 @@ interface IOutput { * @param string $domain * @param bool $secure * @param bool $httpOnly + * @param string $sameSite (added in 20) * @since 8.1.0 */ - public function setCookie($name, $value, $expire, $path, $domain, $secure, $httpOnly); + public function setCookie($name, $value, $expire, $path, $domain, $secure, $httpOnly, $sameSite = 'Lax'); } diff --git a/lib/public/AppFramework/Http/Response.php b/lib/public/AppFramework/Http/Response.php index 6f418e42553..832e0b96247 100644 --- a/lib/public/AppFramework/Http/Response.php +++ b/lib/public/AppFramework/Http/Response.php @@ -133,11 +133,12 @@ class Response { * @param \DateTime|null $expireDate Date on that the cookie should expire, if set * to null cookie will be considered as session * cookie. + * @param string $sameSite The samesite value of the cookie. Defaults to Lax. Other possibilities are Strict or None * @return $this * @since 8.0.0 */ - public function addCookie($name, $value, \DateTime $expireDate = null) { - $this->cookies[$name] = ['value' => $value, 'expireDate' => $expireDate]; + public function addCookie($name, $value, \DateTime $expireDate = null, $sameSite = 'Lax') { + $this->cookies[$name] = ['value' => $value, 'expireDate' => $expireDate, 'sameSite' => $sameSite]; return $this; } diff --git a/tests/lib/AppFramework/Http/ResponseTest.php b/tests/lib/AppFramework/Http/ResponseTest.php index f33d0a0089d..ea1e74de50e 100644 --- a/tests/lib/AppFramework/Http/ResponseTest.php +++ b/tests/lib/AppFramework/Http/ResponseTest.php @@ -108,10 +108,12 @@ class ResponseTest extends \Test\TestCase { 'foo' => [ 'value' => 'bar', 'expireDate' => null, + 'sameSite' => 'Lax', ], 'bar' => [ 'value' => 'foo', - 'expireDate' => new \DateTime('1970-01-01') + 'expireDate' => new \DateTime('1970-01-01'), + 'sameSite' => 'Lax', ] ]; $this->assertEquals($expectedResponse, $this->childResponse->getCookies()); @@ -143,7 +145,8 @@ class ResponseTest extends \Test\TestCase { $expected = [ 'foo' => [ 'value' => 'expired', - 'expireDate' => new \DateTime('1971-01-01') + 'expireDate' => new \DateTime('1971-01-01'), + 'sameSite' => 'Lax', ] ]; @@ -159,11 +162,13 @@ class ResponseTest extends \Test\TestCase { $expected = [ 'foo' => [ 'value' => 'bar', - 'expireDate' => null + 'expireDate' => null, + 'sameSite' => 'Lax', ], 'bar' => [ 'value' => 'foo', - 'expireDate' => null + 'expireDate' => null, + 'sameSite' => 'Lax', ] ]; $cookies = $this->childResponse->getCookies(); @@ -173,11 +178,13 @@ class ResponseTest extends \Test\TestCase { $expected = [ 'foo' => [ 'value' => 'expired', - 'expireDate' => new \DateTime('1971-01-01') + 'expireDate' => new \DateTime('1971-01-01'), + 'sameSite' => 'Lax', ], 'bar' => [ 'value' => 'expired', - 'expireDate' => new \DateTime('1971-01-01') + 'expireDate' => new \DateTime('1971-01-01'), + 'sameSite' => 'Lax', ] ];