You've already forked postfixadmin
mirror of
https://github.com/postfixadmin/postfixadmin.git
synced 2026-10-24 12:19:19 +03:00
possible fix for https://github.com/postfixadmin/postfixadmin/issues/967 CSRF Token changes : rather than have one PFA_Token value in $_SESSION, store a list of them, where each value has a time stamp it was issued on. The aim is to allow the user to have multiple browser tabs open at once - and not have the last tab that loaded trample on others. Tokens expire after 1 hour. Adds a Smarty helper function `{CSRF_Token}` which will output `<input type=hidden name=CSRF_Token value=asdf123>` or `{CSRF_Token type=url}` which outputs a literal string like 'asdf123' suitable for placing in a URL. Adds a PHP exception handler in public/common.php, which could be used to display a more friendly error message/response (but at the moment is fairly minimal). Removes most uses of `die()` within the codebase, and instead moves to throw an exception
46 lines
1.2 KiB
PHP
46 lines
1.2 KiB
PHP
<?php
|
|
|
|
class CsrfToken
|
|
{
|
|
public static function generate(): string
|
|
{
|
|
if (!isset($_SESSION['CSRF_Tokens']) || !is_array($_SESSION['CSRF_Tokens'])) {
|
|
$_SESSION['CSRF_Tokens'] = [];
|
|
}
|
|
|
|
// remove any expired tokens
|
|
foreach ($_SESSION['CSRF_Tokens'] as $key => $value) {
|
|
if ($value < (time())) {
|
|
unset($_SESSION['CSRF_Tokens'][$key]);
|
|
}
|
|
}
|
|
$token = bin2hex(random_bytes(16));
|
|
$_SESSION['CSRF_Tokens'][$token] = (time() + 3600); // is an hour an acceptable expiry time?
|
|
return $token;
|
|
}
|
|
|
|
/**
|
|
* @param string $token
|
|
* @return bool
|
|
* @throws CsrfInvalidException
|
|
*/
|
|
public static function assertValid(string $token): bool
|
|
{
|
|
if (!is_array($_SESSION['CSRF_Tokens'])) {
|
|
$_SESSION['CSRF_Tokens'] = [];
|
|
}
|
|
|
|
$value = (int)($_SESSION['CSRF_Tokens'][$token] ?? 0);
|
|
|
|
// token can only be used once.
|
|
unset($_SESSION['CSRF_Tokens'][$token]);
|
|
|
|
// token cannot have expired
|
|
if ($value < time()) {
|
|
throw new CsrfInvalidException("Invalid CSRF token - try refreshing the page and try again?");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
}
|