| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- <?php
- // auth.php – shared admin authentication helper
- // Include at the top of every admin page.
- require_once __DIR__ . '/../db.php';
- session_name('packit_admin');
- // Scope the cookie to the admin directory, keep it off JavaScript, and never
- // let it travel cross-site (which is what makes the CSRF tokens below the
- // second line of defence rather than the only one).
- $adminPath = rtrim(str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'] ?? '/admin/x.php')), '/') . '/';
- session_set_cookie_params([
- 'lifetime' => 0,
- 'path' => $adminPath,
- 'httponly' => true,
- 'secure' => request_is_https(),
- 'samesite' => 'Strict',
- ]);
- session_start();
- define('ADMIN_LOGGED_IN', isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true);
- function require_admin(): void {
- if (!ADMIN_LOGGED_IN) {
- header('Location: ' . admin_url('login.php'));
- exit;
- }
- }
- function admin_url(string $page): string {
- return $page;
- }
- function admin_logout(): void {
- $_SESSION = [];
- if (ini_get('session.use_cookies')) {
- $p = session_get_cookie_params();
- setcookie(session_name(), '', time() - 42000,
- $p['path'], $p['domain'], $p['secure'], $p['httponly']);
- }
- session_destroy();
- header('Location: login.php');
- exit;
- }
- // ---------------------------------------------------------------------------
- // CSRF
- // ---------------------------------------------------------------------------
- /** Per-session token, minted on first use and reused for the session's life. */
- function csrf_token(): string {
- if (empty($_SESSION['csrf_token'])) {
- $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
- }
- return $_SESSION['csrf_token'];
- }
- /** Hidden field to drop into every POST form. */
- function csrf_field(): string {
- return '<input type="hidden" name="csrf_token" value="'
- . htmlspecialchars(csrf_token(), ENT_QUOTES) . '">';
- }
- /**
- * Guard for every state-changing POST handler. Without this, any page an
- * admin visits while logged in could post to us on their behalf.
- */
- function require_csrf(): void {
- $sent = $_POST['csrf_token'] ?? '';
- if (!is_string($sent) || $sent === '' || !hash_equals(csrf_token(), $sent)) {
- http_response_code(403);
- exit('<p style="font-family:system-ui,sans-serif">Invalid or expired form token. '
- . 'Go back, reload the page and try again.</p>');
- }
- }
|