src/Service/SessionTokenService.php
<?php
namespace App\Service;
use App\Helper\RandomDataGeneratorHelper;
use Exception;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
/**
* Class SessionTokenService
*
* Provides methods to generate, compare, store and retrieve custom random tokens in the session. It's akin to the CSRF
* tokens before the randomization introduced in 5.3
* (see https://symfony.com/blog/new-in-symfony-5-3-better-protection-against-breach-attack)
*
* @package App\Service
*/
class SessionTokenService
{
const TOKEN_KEY_PREFIX = 'session_token_';
private SessionInterface $session;
public function __construct(SessionInterface $session)
{
$this->session = $session;
}
/**
* @param string $key
* @return string
* @throws Exception
*/
public function get(string $key): string
{
$existingToken = $this->session->get($this->generateKey($key));
if (is_null($existingToken)) {
return $this->refresh($key);
}
return $existingToken;
}
private function generateKey(string $suffix): string
{
return self::TOKEN_KEY_PREFIX . $suffix;
}
/**
* @param string $key
* @param string $value
* @return bool
* @throws Exception
*/
public function isValid(string $key, string $value): bool
{
return $this->get($key) === $value;
}
/**
* @param string $key
* @return string
* @throws Exception
*/
public function refresh(string $key): string
{
return $this->set($key);
}
/**
* @param string $key
* @return string
* @throws Exception
*/
private function set(string $key): string
{
$value = RandomDataGeneratorHelper::randomString();
$this->session->set($this->generateKey($key), $value);
return $value;
}
}
src/Twig/Extension/SessionTokenExtension.php
<?php
namespace App\Twig\Extension;
use App\Service\SessionTokenService;
use Exception;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
/**
* Class SessionTokenExtension
* @package App\Twig\Extension
*/
class SessionTokenExtension extends AbstractExtension
{
private SessionTokenService $sessionTokenService;
public function __construct(SessionTokenService $sessionTokenService)
{
$this->sessionTokenService = $sessionTokenService;
}
/**
* @return array
*/
public function getFunctions(): array
{
return [
new TwigFunction('session_token', [$this, 'sessionToken'])
];
}
/**
* @param string $key
* @return string
* @throws Exception
*/
public function sessionToken(string $key): string
{
return $this->sessionTokenService->get($key);
}
}