<commit_before><?php declare(strict_types=1);
/**
 * @author <NAME> <<EMAIL>>
 * @copyright 2012 <NAME>
 * @see https://www.elabftw.net Official website
 * @license AGPL-3.0
 * @package elabftw
 */

namespace Elabftw\Elabftw;

use Defuse\Crypto\Key;
use Elabftw\Exceptions\ImproperActionException;
use Symfony\Component\HttpFoundation\Request;

/**
 * Prevent CSRF attacks
 */
class Csrf
{
    private string $token = '';

    public function __construct(private Request $Request)
    {
    }

    /**
     * Get the token and generate one if needed
     */
    public function getToken(): string
    {
        if ($this->token === '') {
            $this->token = Key::createNewRandomKey()->saveToAsciiSafeString();
        }

        return $this->token;
    }

    public function setToken(string $token): void
    {
        $this->token = $token;
    }

    /**
     * Validate the form key against the one previously set in Session
     */
    public function validate(): void
    {
        // get requests are not checked
        if ($this->Request->server->get('REQUEST_METHOD') === 'GET') {
            return;
        }

        if ($this->getRequestToken() !== $this->getToken()) {
            // an invalid csrf token is most likely the result of an expired session
            throw new ImproperActionException(_('Your session expired.'));
        }
    }

    private function getRequestToken(): string
    {
        // an Ajax request will have the token in the headers
        if ($this->Request->headers->get('X-Requested-With') === 'XMLHttpRequest') {
            return (string) $this->Request->headers->get('X-CSRF-Token');
        }
        return (string) $this->Request->request->get('csrf');
    }
}<commit_msg>add comments on csrf class<commit_after><?php declare(strict_types=1);
/**
 * @author <NAME> <<EMAIL>>
 * @copyright 2012 <NAME>
 * @see https://www.elabftw.net Official website
 * @license AGPL-3.0
 * @package elabftw
 */

namespace Elabftw\Elabftw;

use Defuse\Crypto\Key;
use Elabftw\Exceptions\ImproperActionException;
use Symfony\Component\HttpFoundation\Request;

/**
 * Prevent Cross Site Request Forgery (CSRF) attacks
 * See https://owasp.org/www-community/attacks/csrf
 *
 * A token is generated and stored in the session. It will be the same during all user session.
 * When a POST request is made, the sent token (in 'csrf' field or as header for Ajax requests) is checked against
 * the stored one and an exception is thrown if they don't match, preventing the request to go through.
 */
class Csrf
{
    private string $token = '';

    public function __construct(private Request $Request)
    {
    }

    /**
     * Get the token and generate one if needed
     */
    public function getToken(): string
    {
        if ($this->token === '') {
            $this->token = Key::createNewRandomKey()->saveToAsciiSafeString();
        }

        return $this->token;
    }

    public function setToken(string $token): void
    {
        $this->token = $token;
    }

    /**
     * Validate the csrf token against the one we have
     */
    public function validate(): void
    {
        // get requests are not checked
        if ($this->Request->server->get('REQUEST_METHOD') === 'GET') {
            return;
        }

        if ($this->getRequestToken() !== $this->getToken()) {
            // an invalid csrf token is most likely the result of an expired session
            throw new ImproperActionException(_('Your session expired.'));
        }
    }

    private function getRequestToken(): string
    {
        // an Ajax request will have the token in the headers
        if ($this->Request->headers->get('X-Requested-With') === 'XMLHttpRequest') {
            return (string) $this->Request->headers->get('X-CSRF-Token');
        }
        return (string) $this->Request->request->get('csrf');
    }
}
{'fraction_non_alphanumeric': 0.13121118012422361, 'fraction_numerical': 0.0036231884057971015, 'mean_word_length': 2.5393772893772892, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 49, 'https://': 3, 'lorem ipsum': 0, 'www.': 3, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2090025', 'n_tokens_mistral': 1128, 'n_tokens_neox': 1096, 'n_words': 325}