Skip to content
This repository was archived by the owner on Jan 30, 2020. It is now read-only.

fixes case sensitivity for SameSite directive #207

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ All notable changes to this project will be documented in this file, in reverse

### Fixed

- Nothing.
- [#207](https://github.com/zendframework/zend-http/pull/207) fixes case sensitivity for SameSite directive.

## 2.11.1 - 2019-12-04

Expand Down
21 changes: 15 additions & 6 deletions src/Header/SetCookie.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
use DateTime;
use Zend\Uri\UriFactory;

use function array_key_exists;
use function gettype;
use function is_scalar;
use function strtolower;

/**
* @throws Exception\InvalidArgumentException
* @see http://www.ietf.org/rfc/rfc2109.txt
Expand Down Expand Up @@ -39,9 +44,9 @@ class SetCookie implements MultipleHeaderInterface
* @internal
*/
const SAME_SITE_ALLOWED_VALUES = [
self::SAME_SITE_STRICT,
self::SAME_SITE_LAX,
self::SAME_SITE_NONE,
'strict' => self::SAME_SITE_STRICT,
'lax' => self::SAME_SITE_LAX,
'none' => self::SAME_SITE_NONE
];

/**
Expand Down Expand Up @@ -337,7 +342,7 @@ public function getFieldValue()
}

$sameSite = $this->getSameSite();
if ($sameSite !== null && in_array($sameSite, self::SAME_SITE_ALLOWED_VALUES, true)) {
if ($sameSite !== null && array_key_exists(strtolower($sameSite), self::SAME_SITE_ALLOWED_VALUES)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

coding style: used functions must be imported with use function statements (under use block, separated by blank line)
Import just those you touched, that will be enough.

$fieldValue .= '; SameSite=' . $sameSite;
}

Expand Down Expand Up @@ -618,13 +623,17 @@ public function getSameSite()
*/
public function setSameSite($sameSite)
{
if ($sameSite !== null && ! in_array($sameSite, self::SAME_SITE_ALLOWED_VALUES, true)) {
if ($sameSite === null) {
$this->sameSite = null;
return $this;
}
if (! array_key_exists(strtolower($sameSite), self::SAME_SITE_ALLOWED_VALUES)) {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid value provided for SameSite directive: "%s"; expected one of: Strict, Lax or None',
is_scalar($sameSite) ? $sameSite : gettype($sameSite)
));
}
$this->sameSite = $sameSite;
$this->sameSite = self::SAME_SITE_ALLOWED_VALUES[strtolower($sameSite)];
return $this;
}

Expand Down
85 changes: 85 additions & 0 deletions test/Header/SetCookieTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
use Zend\Http\Header\MultipleHeaderInterface;
use Zend\Http\Header\SetCookie;

use function strtolower;
use function strtoupper;

class SetCookieTest extends TestCase
{
/**
Expand Down Expand Up @@ -69,6 +72,32 @@ public function testSetCookieConstructorWithSameSite()
$this->assertEquals('Strict', $setCookieHeader->getSameSite());
}

public function testSetCookieConstructorWithSameSiteCaseInsensitive()
{
$setCookieHeader = new SetCookie(
'myname',
'myvalue',
'Wed, 13-Jan-2021 22:23:01 GMT',
'/accounts',
'docs.foo.com',
true,
true,
99,
9,
strtolower(SetCookie::SAME_SITE_STRICT)
);
$this->assertEquals('myname', $setCookieHeader->getName());
$this->assertEquals('myvalue', $setCookieHeader->getValue());
$this->assertEquals('Wed, 13-Jan-2021 22:23:01 GMT', $setCookieHeader->getExpires());
$this->assertEquals('/accounts', $setCookieHeader->getPath());
$this->assertEquals('docs.foo.com', $setCookieHeader->getDomain());
$this->assertTrue($setCookieHeader->isSecure());
$this->assertTrue($setCookieHeader->isHttpOnly());
$this->assertEquals(99, $setCookieHeader->getMaxAge());
$this->assertEquals(9, $setCookieHeader->getVersion());
$this->assertEquals(SetCookie::SAME_SITE_STRICT, $setCookieHeader->getSameSite());
}

public function testSetCookieWithInvalidSameSiteValueThrowException()
{
$this->expectException(InvalidArgumentException::class);
Expand Down Expand Up @@ -105,6 +134,29 @@ public function testSetInvalidSameSiteDirectiveValueViaSetter()
$setCookieHeader->setSameSite('InvalidValue');
}

public function testSameSiteGetterReturnsCanonicalValue()
{
$setCookieHeader = new SetCookie(
'myname',
'myvalue',
'Wed, 13-Jan-2021 22:23:01 GMT',
'/accounts',
'docs.foo.com',
true,
true,
99,
9,
SetCookie::SAME_SITE_STRICT
);
$this->assertEquals(SetCookie::SAME_SITE_STRICT, $setCookieHeader->getSameSite());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also test setSameSite() explicitly. Just once would be enough.


$setCookieHeader->setSameSite(strtolower(SetCookie::SAME_SITE_LAX));
$this->assertEquals(SetCookie::SAME_SITE_LAX, $setCookieHeader->getSameSite());

$setCookieHeader->setSameSite(strtoupper(SetCookie::SAME_SITE_NONE));
$this->assertEquals(SetCookie::SAME_SITE_NONE, $setCookieHeader->getSameSite());
}

public function testSetCookieFromStringWithQuotedValue()
{
$setCookieHeader = SetCookie::fromString('Set-Cookie: myname="quotedValue"');
Expand Down Expand Up @@ -161,6 +213,39 @@ public function testSetCookieFromStringCanCreateSingleHeader()
$this->assertTrue($setCookieHeader->isSecure());
$this->assertTrue($setCookieHeader->isHttponly());
$this->assertEquals(setCookie::SAME_SITE_STRICT, $setCookieHeader->getSameSite());

$setCookieHeader = SetCookie::fromString(
'set-cookie: myname=myvalue; Domain=docs.foo.com; Path=/accounts;'
. 'Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure; HttpOnly; SameSite=strict'
);
$this->assertInstanceOf(MultipleHeaderInterface::class, $setCookieHeader);
$this->assertEquals('myname', $setCookieHeader->getName());
$this->assertEquals('myvalue', $setCookieHeader->getValue());
$this->assertEquals('docs.foo.com', $setCookieHeader->getDomain());
$this->assertEquals('/accounts', $setCookieHeader->getPath());
$this->assertEquals('Wed, 13-Jan-2021 22:23:01 GMT', $setCookieHeader->getExpires());
$this->assertTrue($setCookieHeader->isSecure());
$this->assertTrue($setCookieHeader->isHttponly());
$this->assertEquals(setCookie::SAME_SITE_STRICT, $setCookieHeader->getSameSite());
}

public function testFieldValueWithSameSiteCaseInsensitive()
{
$setCookieHeader = SetCookie::fromString(
'set-cookie: myname=myvalue; SameSite=Strict'
);
$this->assertEquals(
'myname=myvalue; SameSite=Strict',
$setCookieHeader->getFieldValue()
);

$setCookieHeader = SetCookie::fromString(
'set-cookie: myname=myvalue; SameSite=strict'
);
$this->assertEquals(
'myname=myvalue; SameSite=Strict',
$setCookieHeader->getFieldValue()
);
}

public function testSetCookieFromStringCanCreateMultipleHeaders()
Expand Down