Skip to main content

Overview

Zoo Arcadia implements a secure authentication system with session-based login, CSRF protection, and automatic session expiration. All authentication is handled through the AuthPagesController.

Login Flow

The authentication process follows these steps:
1

User submits credentials

Users enter their username/email and password on the login page at /auth/pages/login.
2

CSRF token verification

The system verifies the CSRF token to prevent cross-site request forgery attacks.
if (!csrf_verify('login_form')) {
    $_SESSION["login_error"] = "Invalid request. Please try again.";
    header('Location: /auth/pages/login');
    exit();
}
3

Database lookup

The system searches for the user by username OR email:
$query = "SELECT u.*, e.email, r.role_name
          FROM users u 
          LEFT JOIN employees e ON u.employee_id = e.id_employee 
          LEFT JOIN roles r ON u.role_id = r.id_role
          WHERE u.username = :login OR e.email = :login";
4

Password verification

The system compares the provided password with the stored password.
The current implementation uses plain text password comparison. In production, this should be replaced with password_verify() for hashed passwords.
5

Account status check

The system verifies that the account is active:
if ($user['is_active'] == 0) {
    $_SESSION["login_error"] = "Your account is deactivated. Please contact the administrator.";
    header('Location: /auth/pages/login');
    exit();
}
6

Session initialization

On successful login, the system creates a session with user data and permissions:
$_SESSION["user"] = $user;
$_SESSION["loggedin"] = true;
$_SESSION["last_activity"] = time();
$_SESSION["user"]["permissions"] = User::getAllUserPermissions($user['id_user']);

Session Management

Session Timeout

Zoo Arcadia implements automatic session expiration for security:
  • Timeout Duration: 11 hours (39,600 seconds)
  • Check Location: App/router.php:92-99
  • Behavior: Sessions are automatically expired after 11 hours of inactivity
$sessionTimeout = 39600; // 11 hours in seconds

if (isset($_SESSION['last_activity']) && 
    (time() - $_SESSION['last_activity'] > $sessionTimeout)) {
    session_unset();
    session_destroy();
    header("Location: /auth/pages/login?msg=session_expired");
    exit();
}

Session Data Structure

When a user logs in, the session stores:
$_SESSION['loggedin']
boolean
Authentication status (always true when logged in)
$_SESSION['user']
array
User information including:
  • id_user: User ID
  • username: Username
  • role_name: Role name (Admin, Veterinary, Employee)
  • employee_id: Associated employee ID
  • permissions: Array of permission strings
$_SESSION['last_activity']
integer
Unix timestamp of the last activity (updated on each request)

Security Features

CSRF Protection

All forms use CSRF tokens to prevent cross-site request forgery:
// Generate token in form
<?php csrf_field('login_form'); ?>

// Verify token on submission
if (!csrf_verify('login_form')) {
    // Handle invalid token
}
CSRF tokens are unique per form and prevent unauthorized form submissions from external sites.

Input Validation

The system validates and sanitizes all inputs:
// Trim and limit input length
$loginInput = trim($loginInput);
$loginInput = substr($loginInput, 0, 255);

// Validate not empty
if (empty($loginInput)) {
    $_SESSION["login_error"] = "Username or email is required.";
    header('Location: /auth/pages/login');
    exit();
}

Secure Session Cookies

Session cookies are configured with security flags:
  • httponly: Prevents JavaScript access to cookies
  • secure: Ensures cookies are only sent over HTTPS (in production)
  • path and domain: Restricts cookie scope

Logout Process

The logout process (/auth/pages/logout) thoroughly cleans up the session:
1

Clear session variables

$_SESSION = array();
2

Delete session cookie

if (ini_get("session.use_cookies")) {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
}
3

Destroy session

session_destroy();
4

Redirect to login

header("Location: /auth/pages/login");
exit();

Error Handling

The system provides clear error messages for common issues:
  • User not found: “User not found or password incorrect.”
  • Incorrect password: Redirects to login without specific message (security)
  • Deactivated account: “Your account is deactivated. Please contact the administrator.”
  • Session expired: “msg=session_expired” in URL
  • Invalid CSRF token: “Invalid request. Please try again.”

Code Reference

The authentication system is implemented in:
  • Controller: App/auth/controllers/auth_pages_controller.php:30-151
  • User Model: App/users/models/user.php:100-129 (find user)
  • Permissions: App/users/models/user.php:376-409 (load permissions)
  • Session Check: App/router.php:92-99 (timeout validation)
All authenticated routes should check $_SESSION['loggedin'] and validate permissions before allowing access to protected resources.

Build docs developers (and LLMs) love