Skip to content

Commit

Permalink
Add session handler abstraction
Browse files Browse the repository at this point in the history
  • Loading branch information
odan committed Jan 6, 2021
1 parent a2d2edb commit 1f4f13f
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 34 deletions.
49 changes: 49 additions & 0 deletions src/PhpSessionHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Selective\SameSiteCookie;

/**
* SameSite Cookie Configuration.
*/
final class PhpSessionHandler implements SessionHandlerInterface
{
/**
* {@inheritDoc}
*/
public function getId(): string
{
return (string)session_id();
}

/**
* {@inheritDoc}
*/
public function start(): void
{
session_start();
}

/**
* {@inheritDoc}
*/
public function getName(): ?string
{
return (string)session_name();
}

/**
* {@inheritDoc}
*/
public function getCookieParams(): array
{
return (array)session_get_cookie_params();
}

/**
* {@inheritDoc}
*/
public function isStarted(): bool
{
return session_status() !== PHP_SESSION_ACTIVE;
}
}
43 changes: 19 additions & 24 deletions src/SameSiteCookieMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,27 @@
final class SameSiteCookieMiddleware implements MiddlewareInterface
{
/**
* @var string
* @var SameSiteCookieConfiguration
*/
private $sameSite;
private $configuration;

/**
* @var bool
* @var SessionHandlerInterface
*/
private $httpOnly;

/**
* @var bool
*/
private $secure;
private $sessionHandler;

/**
* The constructor.
*
* @param SameSiteCookieConfiguration $configuration The configuration
* @param SessionHandlerInterface|null $sessionHandler The session handler
*/
public function __construct(SameSiteCookieConfiguration $configuration)
{
$this->sameSite = $configuration->sameSite;
$this->httpOnly = $configuration->httpOnly;
$this->secure = $configuration->secure;
public function __construct(
SameSiteCookieConfiguration $configuration,
SessionHandlerInterface $sessionHandler = null
) {
$this->configuration = $configuration;
$this->sessionHandler = $sessionHandler ?: new PhpSessionHandler();
}

/**
Expand All @@ -54,9 +51,9 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
{
$response = $handler->handle($request);

$sessionId = $request->getAttribute('session_id');
$sessionName = $request->getAttribute('session_name');
$params = $request->getAttribute('session_cookie_params');
$sessionId = $this->sessionHandler->getId();
$sessionName = $this->sessionHandler->getName();
$params = $this->sessionHandler->getCookieParams();

if (!$sessionId || !$sessionName || !$params) {
throw new RuntimeException('The session must be started before samesite cookie can be generated.');
Expand All @@ -67,20 +64,18 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
sprintf('path=%s;', $params['path']),
];

if ($this->secure) {
if ($this->configuration->secure) {
$cookieValues[] = 'Secure;';
}

if ($this->httpOnly) {
if ($this->configuration->httpOnly) {
$cookieValues[] = 'HttpOnly;';
}

if ($this->sameSite) {
$cookieValues[] = sprintf('SameSite=%s;', $this->sameSite);
if ($this->configuration->sameSite) {
$cookieValues[] = sprintf('SameSite=%s;', $this->configuration->sameSite);
}

$response = $response->withHeader('Set-Cookie', implode(' ', $cookieValues));

return $response;
return $response->withHeader('Set-Cookie', implode(' ', $cookieValues));
}
}
29 changes: 19 additions & 10 deletions src/SameSiteSessionMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,27 @@
final class SameSiteSessionMiddleware implements MiddlewareInterface
{
/**
* @var bool
* @var SameSiteCookieConfiguration
*/
private $startSession;
private $configuration;

/**
* @var SessionHandlerInterface
*/
private $sessionHandler;

/**
* The constructor.
*
* @param SameSiteCookieConfiguration $configuration The configuration
* @param SessionHandlerInterface|null $sessionHandler The session handler
*/
public function __construct(SameSiteCookieConfiguration $configuration)
{
$this->startSession = $configuration->startSession;
public function __construct(
SameSiteCookieConfiguration $configuration,
SessionHandlerInterface $sessionHandler = null
) {
$this->configuration = $configuration;
$this->sessionHandler = $sessionHandler ?: new PhpSessionHandler();
}

/**
Expand All @@ -38,14 +47,14 @@ public function __construct(SameSiteCookieConfiguration $configuration)
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
// Start session
if ($this->startSession === true && session_status() !== PHP_SESSION_ACTIVE) {
session_start();
if ($this->configuration->startSession === true && !$this->sessionHandler->isStarted()) {
$this->sessionHandler->start();
}

$request = $request
->withAttribute('session_id', session_id())
->withAttribute('session_name', session_name())
->withAttribute('session_cookie_params', session_get_cookie_params());
->withAttribute('session_id', $this->sessionHandler->getId())
->withAttribute('session_name', $this->sessionHandler->getName())
->withAttribute('session_cookie_params', $this->sessionHandler->getCookieParams());

return $handler->handle($request);
}
Expand Down
44 changes: 44 additions & 0 deletions src/SessionHandlerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Selective\SameSiteCookie;

/**
* The SessionHandlerInterface.
*/
interface SessionHandlerInterface
{
/**
* Get session id.
*
* @return string The id
*/
public function getId(): string;

/**
* Start session.
*
* @retrun void
*/
public function start(): void;

/**
* Get session name.
*
* @return string|null The name
*/
public function getName(): ?string;

/**
* Get cookie params.
*
* @return array<mixed> The params
*/
public function getCookieParams(): array;

/**
* Is session started.
*
* @return bool The session status
*/
public function isStarted(): bool;
}

0 comments on commit 1f4f13f

Please sign in to comment.