Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save thibaut-decherit/68342bfb5b99a708b1b8e5099930a9aa to your computer and use it in GitHub Desktop.
Save thibaut-decherit/68342bfb5b99a708b1b8e5099930a9aa to your computer and use it in GitHub Desktop.
Symfony - SessionTokenService and SessionTokenExtension

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);
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment