48 lines
1.2 KiB
PHP
48 lines
1.2 KiB
PHP
|
|
<?php
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
class TaskCertCsrf
|
||
|
|
{
|
||
|
|
private const TOKEN_KEY = 'task_cert_csrf_token';
|
||
|
|
|
||
|
|
public static function token(): string
|
||
|
|
{
|
||
|
|
if (empty($_SESSION[self::TOKEN_KEY])) {
|
||
|
|
$_SESSION[self::TOKEN_KEY] = bin2hex(random_bytes(32));
|
||
|
|
}
|
||
|
|
|
||
|
|
return (string) $_SESSION[self::TOKEN_KEY];
|
||
|
|
}
|
||
|
|
|
||
|
|
public static function hiddenInput(): string
|
||
|
|
{
|
||
|
|
return '<input type="hidden" name="csrf_token" value="' . TaskCertView::e(self::token()) . '">';
|
||
|
|
}
|
||
|
|
|
||
|
|
public static function validate(?string $token): bool
|
||
|
|
{
|
||
|
|
if ($token === null || $token === '') {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
$sessionToken = (string) ($_SESSION[self::TOKEN_KEY] ?? '');
|
||
|
|
if ($sessionToken === '') {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return hash_equals($sessionToken, $token);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static function assertValidFromRequest(bool $jsonResponse = true): void
|
||
|
|
{
|
||
|
|
$token = TaskCertRequest::postString('csrf_token');
|
||
|
|
if ($token === '') {
|
||
|
|
$token = (string) ($_SERVER['HTTP_X_CSRF_TOKEN'] ?? '');
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!self::validate($token)) {
|
||
|
|
TaskCertResponse::error('CSRF validation failed', 419, $jsonResponse);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|