Skip to content

Commit

Permalink
Init
Browse files Browse the repository at this point in the history
  • Loading branch information
odan committed Sep 16, 2019
1 parent 03803db commit 005c653
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 36 deletions.
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,33 +31,36 @@ IE Mobile, UC Browser for Android.

Further details can be found here:

* [https://web.dev/samesite-cookies-explained](SameSite cookies explained)
* [SameSite cookies explained](https://web.dev/samesite-cookies-explained)
* [CSRF is (really) dead](https://scotthelme.co.uk/csrf-is-really-dead/)
* [PHP setcookie “SameSite=Strict”?](https://stackoverflow.com/questions/39750906/php-setcookie-samesite-strict)
* [How to Set a cookie attribute Samesite value in PHP ?](https://www.tutorialshore.com/how-to-set-a-cookie-attribute-samesite-value-in-php/)
* [Can I use SameSite?](https://caniuse.com/#feat=same-site-cookie-attribute)

## Usage
## Slim 4 integration

Slim 4 uses a LIFO (last in, first out) middleware stack,
so we have to add the middleware in reverse order:

```php
<?php

use Selective\SameSiteCookie\SameSiteCookieMiddlware;
use Selective\SameSiteCookie\SameSiteCookieConfiguration;
use Selective\SameSiteCookie\SameSiteCookieMiddleware;
use Selective\SameSiteCookie\SameSiteSessionMiddleware;
use Slim\Factory\AppFactory;

$app = AppFactory::create();

// ...

$configuration = new SameSiteCookieConfiguration();

// Register the samesite cookie middleware
$app->add(new SameSiteCookieMiddlware(true));
$app->add(new SameSiteCookieMiddleware($configuration));

// Start the native PHP session handler and fetch the session attributes
$app->add(new SameSiteSessionMiddleware('Lax', true, true));
$app->add(new SameSiteSessionMiddleware($configuration));

// ...

Expand Down
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
"psr/http-server-middleware": "^1.0"
},
"require-dev": {
"nyholm/psr7": "^1.1",
"overtrue/phplint": "^1.1",
"phpunit/phpunit": "^7",
"phpstan/phpstan-shim": "^0.11",
"phpunit/phpunit": "^7",
"relay/relay": "^2.0",
"squizlabs/php_codesniffer": "^3.4"
},
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php"
<phpunit bootstrap="tests/boostrap.php"
colors="true"
backupGlobals="false"
backupStaticAttributes="false"
Expand Down
29 changes: 29 additions & 0 deletions src/SameSiteCookieConfiguration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Selective\SameSiteCookie;

/**
* SameSite Cookie Configuration.
*/
final class SameSiteCookieConfiguration
{
/**
* @var bool Start the session
*/
public $startSession = true;

/**
* @var string Send cookie only via a href link. Values: 'Lax' or 'Strict'.
*/
public $sameSite = 'Lax';

/**
* @var bool Prevents cookies from being read by scripts. Should be enabled.
*/
public $httpOnly = true;

/**
* @var bool Provide cookies only via ssl. Should be enabled in production.
*/
public $secure = true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
/**
* SameSite Cookie Middleware.
*/
final class SameSiteCookieMiddlware implements MiddlewareInterface
final class SameSiteCookieMiddleware implements MiddlewareInterface
{
/**
* @var string
Expand All @@ -30,15 +30,13 @@ final class SameSiteCookieMiddlware implements MiddlewareInterface
/**
* The constructor.
*
* @param string $sameSite Send cookie only via a href link. Values: 'Lax' or 'Strict'.
* @param bool $httpOnly Prevents cookies from being read by scripts. Should be enabled.
* @param bool $secure Provide cookies only via ssl. Should be enabled in production.
* @param SameSiteCookieConfiguration $configuration The configuration
*/
public function __construct(string $sameSite = 'Lax', bool $httpOnly = true, bool $secure = false)
public function __construct(SameSiteCookieConfiguration $configuration)
{
$this->sameSite = $sameSite;
$this->httpOnly = $httpOnly;
$this->secure = $secure;
$this->sameSite = $configuration->sameSite;
$this->httpOnly = $configuration->httpOnly;
$this->secure = $configuration->secure;
}

/**
Expand All @@ -57,20 +55,6 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
$sessionName = $request->getAttribute('session_name');
$params = $request->getAttribute('session_cookie_params');

if (version_compare(PHP_VERSION, '7.3.0') >= 0) {
// Remove invalid key
unset($params['lifetime']);

$params['samesite'] = $this->sameSite;
$params['httponly'] = $this->httpOnly;
$params['secure'] = $this->secure;

setcookie($sessionName, $sessionId, $params);

return $response;
}

// For older PHP versions
$cookieValues = [
sprintf('%s=%s;', $sessionName, $sessionId),
sprintf('path=%s;', $params['path']),
Expand All @@ -88,8 +72,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
$cookieValues[] = sprintf('SameSite=%s;', $this->sameSite);
}

//$response = $response->withHeader('Set-Cookie', implode(' ', $cookieValues));
header('Set-Cookie: ' . implode(' ', $cookieValues));
$response = $response->withHeader('Set-Cookie', implode(' ', $cookieValues));

return $response;
}
Expand Down
6 changes: 3 additions & 3 deletions src/SameSiteSessionMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ final class SameSiteSessionMiddleware implements MiddlewareInterface
/**
* The constructor.
*
* @param bool $startSession The the session
* @param SameSiteCookieConfiguration $configuration The configuration
*/
public function __construct(bool $startSession = true)
public function __construct(SameSiteCookieConfiguration $configuration)
{
$this->startSession = $startSession;
$this->startSession = $configuration->startSession;
}

/**
Expand Down
41 changes: 41 additions & 0 deletions tests/MiddlewareTestTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Selective\SameSiteCookie\Test;

use Nyholm\Psr7\Factory\Psr17Factory;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Relay\Relay;

/**
* Test.
*/
trait MiddlewareTestTrait
{
/**
* Run middleware stack.
*
* @param array $queue The queue
*
* @return ResponseInterface The response
*/
protected function runQueue(array $queue): ResponseInterface
{
$queue[] = new ResponseFactoryMiddleware();

$request = $this->createRequest();
$relay = new Relay($queue);

return $relay->handle($request);
}

/**
* Factory.
*
* @return ServerRequestInterface
*/
protected function createRequest(): ServerRequestInterface
{
return (new Psr17Factory())->createServerRequest('GET', '/');
}
}
28 changes: 28 additions & 0 deletions tests/ResponseFactoryMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Selective\SameSiteCookie\Test;

use Nyholm\Psr7\Factory\Psr17Factory;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

/**
* Middleware.
*/
final class ResponseFactoryMiddleware implements MiddlewareInterface
{
/**
* Invoke middleware.
*
* @param ServerRequestInterface $request The request
* @param RequestHandlerInterface $handler The handler
*
* @return ResponseInterface The response
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
return (new Psr17Factory())->createResponse();
}
}
20 changes: 18 additions & 2 deletions tests/SameSiteCookieMiddlewareTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,35 @@
namespace Selective\SameSiteCookie\Test;

use PHPUnit\Framework\TestCase;
use Selective\SameSiteCookie\SameSiteCookieConfiguration;
use Selective\SameSiteCookie\SameSiteCookieMiddleware;
use Selective\SameSiteCookie\SameSiteSessionMiddleware;

/**
* Test.
*/
class SameSiteCookieMiddlewareTest extends TestCase
{
use MiddlewareTestTrait;

/**
* Test.
*
* @return void
*/
public function testTrue(): void
public function testDefaultConfiguration(): void
{
static::assertTrue(true);
$configuration = new SameSiteCookieConfiguration();

session_id('v3absd19o9pi6cjvhb5pkmsfo9');

$response = $this->runQueue([
new SameSiteSessionMiddleware($configuration),
new SameSiteCookieMiddleware($configuration),
]);

$cookie = $response->getHeaderLine('Set-Cookie');
static::assertSame('PHPSESSID=v3absd19o9pi6cjvhb5pkmsfo9; path=/; Secure; HttpOnly; SameSite=Lax;', $cookie);
static::assertSame('', (string)$response->getBody());
}
}
5 changes: 5 additions & 0 deletions tests/boostrap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

require __DIR__ . '/../vendor/autoload.php';

ob_start();

0 comments on commit 005c653

Please sign in to comment.