Skip to content

Commit

Permalink
Merge pull request #37 from xmorave2/feature/samesite
Browse files Browse the repository at this point in the history
Add cookie_samesite parameter
  • Loading branch information
weierophinney authored Jun 30, 2021
2 parents 442588d + 358c0a3 commit c4e19f1
Show file tree
Hide file tree
Showing 8 changed files with 287 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/book/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Option | Data Type | Description
`cookie_httponly` | `boolean` | Marks the cookie as accessible only through the HTTP protocol.
`cookie_lifetime` | `integer` | Specifies the lifetime of the cookie in seconds which is sent to the browser.
`cookie_path` | `string` | Specifies path to set in the session cookie.
`cookie_samesite` | `string` | Specifies whether cookies should be sent along with cross-site requests. (Since 2.11.0)
`cookie_secure` | `boolean` | Specifies whether cookies should only be sent over secure connections.
`entropy_length` | `integer` | Specifies the number of bytes which will be read from the file specified in entropy_file. Removed in PHP 7.1.0.
`entropy_file` | `string` | Defines a path to an external resource (file) which will be used as an additional entropy. Removed in PHP 7.1.0.
Expand Down
15 changes: 15 additions & 0 deletions src/Config/SameSiteCookieCapableInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Laminas\Session\Config;

interface SameSiteCookieCapableInterface
{
/**
* @param string $cookieSameSite
* @return self
*/
public function setCookieSameSite($cookieSameSite);

/** @return string */
public function getCookieSameSite();
}
36 changes: 35 additions & 1 deletion src/Config/StandardConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
/**
* Standard session configuration
*/
class StandardConfig implements ConfigInterface
class StandardConfig implements ConfigInterface, SameSiteCookieCapableInterface
{
/**
* session.name
Expand Down Expand Up @@ -70,6 +70,13 @@ class StandardConfig implements ConfigInterface
*/
protected $cookieDomain;

/**
* session.cookie_samesite
*
* @var string
*/
protected $cookieSameSite;

/**
* session.cookie_secure
*
Expand Down Expand Up @@ -511,6 +518,32 @@ public function getCookieDomain()
return $this->cookieDomain;
}

/**
* Set session.cookie_samesite
*
* @param string $cookieSameSite
* @return StandardConfig
*/
public function setCookieSameSite($cookieSameSite)
{
$this->cookieSameSite = (string) $cookieSameSite;
$this->setStorageOption('cookie_samesite', $this->cookieSameSite);
return $this;
}

/**
* Get session.cookie_samesite
*
* @return string
*/
public function getCookieSameSite()
{
if (null === $this->cookieSameSite) {
$this->cookieSameSite = $this->getStorageOption('cookie_samesite');
}
return $this->cookieSameSite;
}

/**
* Set session.cookie_secure
*
Expand Down Expand Up @@ -912,6 +945,7 @@ public function toArray()
'cookie_httponly' => $this->getCookieHttpOnly(),
'cookie_lifetime' => $this->getCookieLifetime(),
'cookie_path' => $this->getCookiePath(),
'cookie_samesite' => $this->getCookieSameSite(),
'cookie_secure' => $this->getCookieSecure(),
'name' => $this->getName(),
'remember_me_seconds' => $this->getRememberMeSeconds(),
Expand Down
13 changes: 13 additions & 0 deletions src/Service/SessionConfigFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Laminas\ServiceManager\FactoryInterface;
use Laminas\ServiceManager\ServiceLocatorInterface;
use Laminas\Session\Config\ConfigInterface;
use Laminas\Session\Config\SameSiteCookieCapableInterface;
use Laminas\Session\Config\SessionConfig;

use function class_exists;
Expand Down Expand Up @@ -60,6 +61,18 @@ public function __invoke(ContainerInterface $container, $requestedName, ?array $
ConfigInterface::class
));
}

if (
isset($config['cookie_samesite'])
&& ! $sessionConfig instanceof SameSiteCookieCapableInterface
) {
throw new ServiceNotCreatedException(sprintf(
'Invalid configuration class "%s". When configuration option "cookie_samesite" is used,'
. ' the configuration class must implement %s',
$class,
SameSiteCookieCapableInterface::class
));
}
$sessionConfig->setOptions($config);

return $sessionConfig;
Expand Down
24 changes: 24 additions & 0 deletions test/Config/SessionConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,25 @@ public function testSettingInvalidCookieDomainRaisesException2(): void
$this->config->setCookieDomain('D:\\WINDOWS\\System32\\drivers\\etc\\hosts');
}

// session.cookie_samesite

public function testCookieSameSiteDefaultsToIniSettings()
{
$this->assertSame(ini_get('session.cookie_samesite'), $this->config->getCookieSameSite());
}

public function testCookieSameSiteIsMutable()
{
$this->config->setCookieSameSite('Strict');
$this->assertEquals('Strict', $this->config->getCookieSameSite());
}

public function testCookieSameSiteAltersIniSetting()
{
$this->config->setCookieSameSite('Strict');
$this->assertEquals('Strict', ini_get('session.cookie_samesite'));
}

// session.cookie_secure

public function testCookieSecureDefaultsToIniSettings(): void
Expand Down Expand Up @@ -901,6 +920,11 @@ public function optionsProvider(): array
'getCookieDomain',
'getlaminas.org',
],
[
'cookie_samesite',
'getCookieSameSite',
'Lax',
],
[
'cookie_secure',
'getCookieSecure',
Expand Down
13 changes: 13 additions & 0 deletions test/Config/StandardConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,14 @@ public function testSettingInvalidCookieDomainRaisesException2(): void
$this->config->setCookieDomain('D:\\WINDOWS\\System32\\drivers\\etc\\hosts');
}

// session.cookie_samesite

public function testCookieSameSiteIsMutable()
{
$this->config->setCookieSameSite('Strict');
$this->assertEquals('Strict', $this->config->getCookieSameSite());
}

// session.cookie_secure

public function testCookieSecureIsMutable(): void
Expand Down Expand Up @@ -524,6 +532,11 @@ public function optionsProvider(): array
'getCookieDomain',
'getlaminas.org',
],
[
'cookie_samesite',
'getCookieSameSite',
'Lax',
],
[
'cookie_secure',
'getCookieSecure',
Expand Down
18 changes: 18 additions & 0 deletions test/Service/SessionConfigFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
namespace LaminasTest\Session\Service;

use Laminas\ServiceManager\Config;
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
use Laminas\ServiceManager\ServiceManager;
use Laminas\Session\Config\ConfigInterface;
use Laminas\Session\Config\SessionConfig;
use Laminas\Session\Config\StandardConfig;
use Laminas\Session\Service\SessionConfigFactory;
use LaminasTest\Session\TestAsset\TestConfig;
use PHPUnit\Framework\TestCase;

/**
Expand Down Expand Up @@ -73,4 +75,20 @@ public function testServiceReceivesConfiguration(): void
$config = $this->services->get(ConfigInterface::class);
self::assertEquals('laminas', $config->getName());
}

public function testServiceNotCreatedWhenInvalidSamesiteConfig()
{
$this->services->setService(
'config',
[
'session_config' => [
'config_class' => TestConfig::class,
'cookie_samesite' => 'Lax',
],
]
);
$this->expectException(ServiceNotCreatedException::class);
$this->expectExceptionMessage('"cookie_samesite"');
$this->services->get(ConfigInterface::class);
}
}
168 changes: 168 additions & 0 deletions test/TestAsset/TestConfig.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
<?php

namespace LaminasTest\Session\TestAsset;

use Laminas\Session\Config\ConfigInterface;

class TestConfig implements ConfigInterface
{
/**
* @param array $options
* @return void
*/
public function setOptions($options)
{
}

/** @return void */
public function getOptions()
{
}

/**
* @param string $option
* @param mixed $value
* @return void
*/
public function setOption($option, $value)
{
}

/**
* @param string $option
* @return void
*/
public function getOption($option)
{
}

/**
* @param string $option
* @return void
*/
public function hasOption($option)
{
}

/** @return void */
public function toArray()
{
}

/**
* @param string $name
* @return void
*/
public function setName($name)
{
}

/** @return void */
public function getName()
{
}

/**
* @param string $savePath
* @return void
*/
public function setSavePath($savePath)
{
}

/** @return void */
public function getSavePath()
{
}

/**
* @param int $cookieLifetime
* @return void
*/
public function setCookieLifetime($cookieLifetime)
{
}

/** @return void */
public function getCookieLifetime()
{
}

/**
* @param string $cookiePath
* @return void
*/
public function setCookiePath($cookiePath)
{
}

/** @return void */
public function getCookiePath()
{
}

/**
* @param string $cookieDomain
* @return void
*/
public function setCookieDomain($cookieDomain)
{
}

/** @return void */
public function getCookieDomain()
{
}

/**
* @param bool $cookieSecure
* @return void
*/
public function setCookieSecure($cookieSecure)
{
}

/** @return void */
public function getCookieSecure()
{
}

/**
* @param bool $cookieHttpOnly
* @return void
*/
public function setCookieHttpOnly($cookieHttpOnly)
{
}

/** @return void */
public function getCookieHttpOnly()
{
}

/**
* @param bool $useCookies
* @return void
*/
public function setUseCookies($useCookies)
{
}

/** @return void */
public function getUseCookies()
{
}

/**
* @param int $rememberMeSeconds
* @return void
*/
public function setRememberMeSeconds($rememberMeSeconds)
{
}

/** @return void */
public function getRememberMeSeconds()
{
}
}

0 comments on commit c4e19f1

Please sign in to comment.