aboutsummaryrefslogtreecommitdiffstats
path: root/src/app/Csrf.php
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/Csrf.php')
-rw-r--r--src/app/Csrf.php33
1 files changed, 33 insertions, 0 deletions
diff --git a/src/app/Csrf.php b/src/app/Csrf.php
new file mode 100644
index 0000000..a18c5d9
--- /dev/null
+++ b/src/app/Csrf.php
@@ -0,0 +1,33 @@
+<?php
+
+declare(strict_types=1);
+// CSRF token generation and validation.
+// Prevents attackers from tricking logged-in users into submitting unwanted requests.
+// See README.md for a full explanation of the CSRF attack and how tokens prevent it.
+
+namespace App;
+
+class Csrf
+{
+ public static function generate(): string
+ {
+ // Reuse the token for the whole session so multiple tabs/forms work
+ if (empty($_SESSION['csrf_token'])) {
+ $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
+ }
+ return $_SESSION['csrf_token'];
+ }
+
+ public static function validate(string $token): bool
+ {
+ // hash_equals() prevents timing attacks (constant-time comparison)
+ return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
+ }
+
+ public static function field(): string
+ {
+ // Returns a hidden <input> to embed in HTML forms
+ $token = htmlspecialchars(self::generate());
+ return '<input type="hidden" name="csrf_token" value="' . $token . '">';
+ }
+}