Skip to content

Commit

Permalink
cache identity for cookie storage
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Kurowski committed Sep 30, 2022
1 parent 9a987d9 commit ba984f7
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/Bridges/SecurityHttp/CookieStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ final class CookieStorage implements Nette\Security\UserStorage
private string $cookieSameSite = 'Lax';
private ?string $cookieExpiration = null;

/**
* As reading from state reads from HTTP request but saving/clearing stores to HTTP response,
* reading from state after writing to state results in inaccurate results (old data).
* This cached identity balances the gap between request and response.
*/
private ?IIdentity $cachedIdentity = null;


public function __construct(Http\IRequest $request, Http\IResponse $response)
{
Expand All @@ -52,11 +59,13 @@ public function saveAuthentication(IIdentity $identity): void
domain: $this->cookieDomain,
sameSite: $this->cookieSameSite,
);
$this->cachedIdentity = $identity;
}


public function clearAuthentication(bool $clearIdentity): void
{
$this->cachedIdentity = null;
$this->response->deleteCookie(
$this->cookieName,
domain: $this->cookieDomain,
Expand All @@ -66,6 +75,10 @@ public function clearAuthentication(bool $clearIdentity): void

public function getState(): array
{
if ($this->cachedIdentity !== null) {
return [(bool) $this->cachedIdentity, $this->cachedIdentity, null];
}

$uid = $this->request->getCookie($this->cookieName);
$identity = is_string($uid) && strlen($uid) >= self::MIN_LENGTH
? new Nette\Security\SimpleIdentity($uid)
Expand Down
39 changes: 39 additions & 0 deletions tests/Security.Http/CookieStorage.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

/**
* Test: Nette\Bridges\SecurityHttp\CookieStorage
*/

declare(strict_types=1);

use Nette\Bridges\SecurityHttp\CookieStorage;
use Nette\Http\Request;
use Nette\Http\Response;
use Nette\Http\UrlScript;
use Nette\Security\SimpleIdentity;
use Nette\Utils\Random;
use Tester\Assert;


require __DIR__ . '/../bootstrap.php';

$request = new Request(new UrlScript());
$response = new Response();
$storage = new CookieStorage($request, $response);

$uid = Random::generate(15);

// initially, there is nothing stored
Assert::equal([false, null, null], $storage->getState());

// authenticate
$storage->saveAuthentication(new SimpleIdentity($uid));
[$authenticated, $identity, $reason] = $storage->getState();
Assert::true($authenticated);
Assert::equal($uid, $identity->getId());
Assert::null($reason);

// clear authentication
$storage->clearAuthentication(false); // clearIdentity parameter is ignored for cookie storage
[$authenticated, $identity, $reason] = $storage->getState();
Assert::equal([false, null, null], $storage->getState());

0 comments on commit ba984f7

Please sign in to comment.