conn = $conn; $this->userModel = new UserModel($conn); } /** * Authenticate user from Authelia forward auth headers * * @return array User data array * @throws Exception if authentication fails */ public function authenticate() { // Start session if not already started with secure settings if (session_status() === PHP_SESSION_NONE) { // Configure secure session settings ini_set('session.cookie_httponly', 1); ini_set('session.cookie_secure', 1); // Requires HTTPS ini_set('session.cookie_samesite', 'Lax'); // Lax allows redirects from Authelia ini_set('session.use_strict_mode', 1); ini_set('session.gc_maxlifetime', 18000); // 5 hours ini_set('session.cookie_lifetime', 0); // Until browser closes session_start(); } // Check if user is already authenticated in session if (isset($_SESSION['user']) && isset($_SESSION['user']['user_id'])) { // Verify session hasn't expired (5 hour timeout) if (isset($_SESSION['last_activity']) && (time() - $_SESSION['last_activity'] > 18000)) { // Session expired, clear it session_unset(); session_destroy(); session_start(); } else { // Update last activity time $_SESSION['last_activity'] = time(); return $_SESSION['user']; } } // Read Authelia forward auth headers $username = $this->getHeader('HTTP_REMOTE_USER'); $displayName = $this->getHeader('HTTP_REMOTE_NAME'); $email = $this->getHeader('HTTP_REMOTE_EMAIL'); $groups = $this->getHeader('HTTP_REMOTE_GROUPS'); // Check if authentication headers are present if (empty($username)) { // No auth headers - user not authenticated $this->redirectToAuth(); exit; } // Check if user has required group membership if (!$this->checkGroupAccess($groups)) { $this->showAccessDenied($username, $groups); exit; } // Sync user to database (create or update) $user = $this->userModel->syncUserFromAuthelia($username, $displayName, $email, $groups); if (!$user) { throw new Exception("Failed to sync user from Authelia"); } // Regenerate session ID to prevent session fixation attacks session_regenerate_id(true); // Store user in session $_SESSION['user'] = $user; $_SESSION['last_activity'] = time(); // Generate new CSRF token on login require_once __DIR__ . '/CsrfMiddleware.php'; CsrfMiddleware::generateToken(); return $user; } /** * Get header value from server variables * * @param string $header Header name * @return string|null Header value or null if not set */ private function getHeader($header) { if (isset($_SERVER[$header])) { return $_SERVER[$header]; } return null; } /** * Check if user has required group membership * * @param string $groups Comma-separated group names * @return bool True if user has access */ private function checkGroupAccess($groups) { if (empty($groups)) { return false; } // Check for admin or employee group membership $userGroups = array_map('trim', explode(',', strtolower($groups))); $requiredGroups = ['admin', 'employee']; return !empty(array_intersect($userGroups, $requiredGroups)); } /** * Redirect to Authelia login */ private function redirectToAuth() { // Redirect to the auth endpoint (Authelia will handle the redirect back) header('HTTP/1.1 401 Unauthorized'); echo ' Authentication Required

Authentication Required

You need to be logged in to access Tinker Tickets.

Continue to Login
'; exit; } /** * Show access denied page * * @param string $username Username * @param string $groups User groups */ private function showAccessDenied($username, $groups) { header('HTTP/1.1 403 Forbidden'); echo ' Access Denied

Access Denied

You do not have permission to access Tinker Tickets.

Required groups: admin or employee

Username: ' . htmlspecialchars($username) . '
Groups: ' . htmlspecialchars($groups ?: 'none') . '

Please contact your administrator if you believe this is an error.

'; exit; } /** * Get current authenticated user from session * * @return array|null User data or null if not authenticated */ public static function getCurrentUser() { if (session_status() === PHP_SESSION_NONE) { session_start(); } return $_SESSION['user'] ?? null; } /** * Logout current user */ public static function logout() { if (session_status() === PHP_SESSION_NONE) { session_start(); } session_unset(); session_destroy(); } }