Skip to content

Commit

Permalink
Merge pull request Shardj#375 from develart-projects/samesiteCookieHe…
Browse files Browse the repository at this point in the history
…aderParam

added SameSite setCookie param (Shardj#315)
  • Loading branch information
develart-projects authored Aug 30, 2023
2 parents 0464ee9 + e1c2541 commit 8aba653
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 6 deletions.
52 changes: 51 additions & 1 deletion library/Zend/Http/Header/SetCookie.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ class Zend_Http_Header_SetCookie
* @var true
*/
protected $httponly = null;

/**
*
* @var string
*/
protected $sameSite = null;

/**
* Generate a new Cookie object from a cookie string
Expand Down Expand Up @@ -165,6 +171,7 @@ public static function fromString($headerLine, $bypassHeaderFieldName = false)
case 'httponly': $header->setHttponly(true); break;
case 'version' : $header->setVersion((int) $headerValue); break;
case 'maxage' : $header->setMaxAge((int) $headerValue); break;
case 'samesite' : $header->setSameSite($headerValue); break;
default:
// Intentionally omitted
}
Expand All @@ -186,11 +193,12 @@ public static function fromString($headerLine, $bypassHeaderFieldName = false)
* @param bool $httponly
* @param string $maxAge
* @param int $version
* @param string $sameSite
* @return void
* @todo Add validation of each one of the parameters (legal domain, etc.)
*
*/
public function __construct($name = null, $value = null, $expires = null, $path = null, $domain = null, $secure = false, $httponly = false, $maxAge = null, $version = null)
public function __construct($name = null, $value = null, $expires = null, $path = null, $domain = null, $secure = false, $httponly = false, $maxAge = null, $version = null, $sameSite = null)
{
$this->type = 'Cookie';

Expand Down Expand Up @@ -229,6 +237,11 @@ public function __construct($name = null, $value = null, $expires = null, $path
if ($httponly) {
$this->setHttponly($httponly);
}

if( !empty($sameSite) ) {
$this->setSameSite($sameSite);
}

}

/**
Expand Down Expand Up @@ -289,6 +302,10 @@ public function getFieldValue()
if ($this->isHttponly()) {
$fieldValue .= '; HttpOnly';
}

if ($this->hasSameSiteValue()) {
$fieldValue .= '; SameSite=' . $this->getSameSite();
}

return $fieldValue;
}
Expand Down Expand Up @@ -445,7 +462,40 @@ public function getPath()
{
return $this->path;
}

/**
*
* @return string
*/
public function getSameSite() {
return $this->sameSite;
}

/**
*
* @param string $sameSite
* @return void
*/
public function setSameSite($sameSite) {

$validOptions = ['Strict', 'Lax', 'None'];

if( !in_array($sameSite, $validOptions)) {
throw new Zend_Http_Header_Exception_InvalidArgumentException('Invalid SameSite value, use one of: ' . implode(', ', $validOptions) );
}

$this->sameSite = $sameSite;
}

/**
*
* @return bool
*/
public function hasSameSiteValue(): bool {
return empty($this->getSameSite()) === FALSE;
}


/**
* @param boolean $secure
*/
Expand Down
31 changes: 26 additions & 5 deletions tests/Zend/Http/Header/SetCookieTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ public function testSetCookieConstructor()
true,
true,
99,
9
9,
'Strict'
);
$this->assertEquals('myname', $setCookieHeader->getName());
$this->assertEquals('myvalue', $setCookieHeader->getValue());
Expand All @@ -74,6 +75,7 @@ public function testSetCookieConstructor()
$this->assertTrue($setCookieHeader->isHttpOnly());
$this->assertEquals(99, $setCookieHeader->getMaxAge());
$this->assertEquals(9, $setCookieHeader->getVersion());
$this->assertEquals('Strict', $setCookieHeader->getSameSite());
}

public function testSetCookieFromStringCreatesValidSetCookieHeader()
Expand All @@ -91,7 +93,7 @@ public function testSetCookieFromStringCanCreateSingleHeader()

$setCookieHeader = Zend_Http_Header_SetCookie::fromString(
'set-cookie: myname=myvalue; Domain=docs.foo.com; Path=/accounts;'
. 'Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure; HttpOnly'
. 'Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure; HttpOnly; SameSite=Strict'
);
$this->assertTrue($setCookieHeader instanceof Zend_Http_Header_SetCookie);
$this->assertEquals('myname', $setCookieHeader->getName());
Expand All @@ -101,14 +103,15 @@ public function testSetCookieFromStringCanCreateSingleHeader()
$this->assertEquals('Wed, 13-Jan-2021 22:23:01 GMT', $setCookieHeader->getExpires());
$this->assertTrue($setCookieHeader->isSecure());
$this->assertTrue($setCookieHeader->isHttponly());
$this->assertEquals('Strict', $setCookieHeader->getSameSite());
}

public function testSetCookieFromStringCanCreateMultipleHeaders()
{
$setCookieHeaders = Zend_Http_Header_SetCookie::fromString(
'Set-Cookie: myname=myvalue, '
. 'someothername=someothervalue; Domain=docs.foo.com; Path=/accounts;'
. 'Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure; HttpOnly'
. 'Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure; HttpOnly; SameSite=Strict'
);
$this->assertTrue(is_array($setCookieHeaders));

Expand All @@ -126,6 +129,7 @@ public function testSetCookieFromStringCanCreateMultipleHeaders()
$this->assertEquals('/accounts', $setCookieHeader->getPath());
$this->assertTrue($setCookieHeader->isSecure());
$this->assertTrue($setCookieHeader->isHttponly());
$this->assertEquals('Strict', $setCookieHeader->getSameSite());
}

public function testSetCookieGetFieldNameReturnsHeaderName()
Expand All @@ -144,10 +148,11 @@ public function testSetCookieGetFieldValueReturnsProperValue()
$setCookieHeader->setPath('/accounts');
$setCookieHeader->setSecure(true);
$setCookieHeader->setHttponly(true);
$setCookieHeader->setSameSite('Strict');

$target = 'myname=myvalue; Expires=Wed, 13-Jan-2021 22:23:01 GMT;'
. ' Domain=docs.foo.com; Path=/accounts;'
. ' Secure; HttpOnly';
. ' Secure; HttpOnly; SameSite=Strict';

$this->assertEquals($target, $setCookieHeader->getFieldValue());
}
Expand All @@ -162,10 +167,11 @@ public function testSetCookieToStringReturnsHeaderFormattedString()
$setCookieHeader->setPath('/accounts');
$setCookieHeader->setSecure(true);
$setCookieHeader->setHttponly(true);
$setCookieHeader->setSameSite('Strict');

$target = 'Set-Cookie: myname=myvalue; Expires=Wed, 13-Jan-2021 22:23:01 GMT;'
. ' Domain=docs.foo.com; Path=/accounts;'
. ' Secure; HttpOnly';
. ' Secure; HttpOnly; SameSite=Strict';

$this->assertEquals($target, $setCookieHeader->toString());
}
Expand Down Expand Up @@ -377,6 +383,20 @@ public static function validCookieWithInfoProvider()
],
'myname=myvalue; Expires=Wed, 13-Jan-2021 22:23:01 GMT; Domain=docs.foo.com; Path=/accounts; Secure; HttpOnly'
],
[
'Set-Cookie: myname=myvalue; Domain=docs.foo.com; Path=/accounts; Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure; HttpOnly; SameSite=Strict',
[
'name' => 'myname',
'value' => 'myvalue',
'domain' => 'docs.foo.com',
'path' => '/accounts',
'expires' => 'Wed, 13-Jan-2021 22:23:01 GMT',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict',
],
'myname=myvalue; Expires=Wed, 13-Jan-2021 22:23:01 GMT; Domain=docs.foo.com; Path=/accounts; Secure; HttpOnly; SameSite=Strict'
],
];
}

Expand All @@ -387,6 +407,7 @@ public function invalidCookieComponentValues()
'setValue' => ['setValue', "This\r\nis\nan\revil\r\n\r\nvalue"],
'setDomain' => ['setDomain', "This\r\nis\nan\revil\r\n\r\nvalue"],
'setPath' => ['setPath', "This\r\nis\nan\revil\r\n\r\nvalue"],
'setSameSite' => ['setSameSite', "This\r\nis\nan\revil\r\n\r\nvalue"],
];
}

Expand Down

0 comments on commit 8aba653

Please sign in to comment.