PPPHP

Security API – Security Class

The Security class provides a complete authentication, authorisation and protection toolkit. It covers user login/logout, session management, permissions, owner‑based row‑level security, password hashing, CSRF, rate limiting, TOTP two‑factor authentication and secure "Remember Me" cookies. Every method is static and safe – no manual session manipulation needed.

Contents

Authentication

Login – Standard username/password

// Basic login
if (Security::Login($username, $password)) {
    echo "Welcome, " . Security::CurrentUsername();
} else {
    echo "Invalid credentials.";
}

Login with “Remember Me”

// Pass true to set a persistent cookie (30 days)
Security::Login($username, $password, true);

Login without password (e.g. after OAuth)

// LoginAs only needs a username – no password check
Security::LoginAs('john.doe');

Check credentials without logging in

if (Security::CheckUsernamePassword('admin', 'secret')) {
    // valid, but session is unchanged
}

Logout

Security::Logout();
// After logout, all session data is removed.
// You should redirect to the login page.
header('Location: /login');

User State

// Is anybody logged in?
if (Security::IsLoggedIn()) { … }

// Is the current user a superadmin?
if (Security::IsAdmin()) { … }

// Is the visitor a guest?
if (Security::IsGuest()) { … }

// Get the username
echo Security::CurrentUsername();   // e.g. "john.doe"

// Get the role/group
echo Security::CurrentUserGroup();  // "superadmin", "developer", "user"

// Get all groups (array) – currently wraps role in an array
$groups = Security::CurrentUserGroups();

// Full user data array (cached in session)
$user = Security::CurrentUserData();
echo $user['email'];

// Reload user data from database
Security::RefreshUserData();

Table‑level Permissions

Each table has seven permission bits: Add, Delete, Edit, Search/List, Print/Export, Import, Manage (admin).

Set permissions for a table

// Using a string (each letter grants the corresponding right)
Security::SetPermissions('orders', 'ADES');   // can add, delete, edit, search

// Using an array
Security::SetPermissions('products', [
    'A' => true,
    'D' => false,
    'E' => true,
    'S' => true,
    'P' => true,
    'I' => false,
    'M' => false
]);

Check a specific permission

if (Security::HasPermission('orders', 'E')) {
    echo "User can edit orders.";
} else {
    echo "Edit access denied.";
}

Retrieve all permissions for a table

$perms = Security::GetPermissions('orders');
if ($perms['A']) { echo "Can add"; }

Allowed Pages

Fine‑grained control over which individual pages a user can access for a table and page type (list, add, edit, view, print, search).

Set allowed pages

// Allow only the "summary" and "details" pages for the list type
Security::SetAllowedPages('orders', 'list', ['summary', 'details']);

// A single page as a string
Security::SetAllowedPages('orders', 'add', 'order_add');

Get allowed pages

$pages = Security::GetAllowedPages('orders', 'list');
if (in_array('summary', $pages)) {
    echo "Summary page is allowed.";
}

OwnerID (Row‑level Security)

When a table has “own data only” security, the system needs to know which ID belongs to the current user. OwnerID stores that value.

Set OwnerID

// After login, set the user's ID as the owner for the customers table
Security::SetOwnerId('customers', $user['id']);

Get OwnerID

$ownerId = Security::GetOwnerId('customers');
DB::Select('customers', ['assigned_to' => $ownerId]);

Password Utilities

Hash a password

$hashed = Security::HashPassword('mySecureP@ss');
// Uses bcrypt (PASSWORD_DEFAULT)

Verify a password

if (Security::VerifyPassword('mySecureP@ss', $hashed)) {
    // valid
}

Check if a hash needs rehashing

if (Security::PasswordNeedsRehash($hashed)) {
    $newHash = Security::HashPassword($newPassword);
    DB::Update('users', ['password' => $newHash], ['id' => $userId]);
}

Remember Me

// When logging in with rememberMe = true, a long‑lived cookie is set.
Security::Login($username, $password, true);

// On subsequent visits, before any authentication check:
if (!Security::IsLoggedIn() && Security::LoginFromRememberMe()) {
    // User was logged in via cookie; session is now active.
}
Security note: The “Remember Me” feature stores a hashed token in the database. The plain token is never stored on the server.

CSRF Protection

// Generate a CSRF token (stored in session)
$token = Security::CSRF()->Token();

// Output a hidden field in a form
echo Security::CSRF()->HiddenField();

// Check a submitted token
if (!Security::CSRF()->Check($_POST['_token'] ?? '')) {
    die('Invalid CSRF token.');
}

// Regenerate token (e.g. after login)
Security::CSRF()->Regenerate();
Important: Always include the CSRF token in POST forms. The Check() method uses hash_equals() for timing‑safe comparison.

Rate Limiting

// Protect a login endpoint from brute‑force attacks
$key = 'login:' . $_SERVER['REMOTE_ADDR'];
$maxAttempts = 5;
$window = 60; // 60 seconds

if (!Security::RateLimit()->Check($key, $maxAttempts, $window)) {
    $remaining = Security::RateLimit()->Remaining($key, $maxAttempts, $window);
    die("Too many attempts. Try again in $window seconds.");
}

// After a failed login:
Security::RateLimit()->Hit($key);

// After a successful login, you can clear the rate limit:
// (Manually unset the session key or wait for the window to expire)

Two‑factor Authentication (TOTP)

// Generate a secret for a user
$secret = Security::TOTP()->GenerateSecret();   // e.g. "JBSWY3DPEHPK3PXP"
DB::Update('users', ['totp_secret' => $secret], ['id' => $userId]);

// Get the QR code URL (for apps like Google Authenticator)
$qrUrl = Security::TOTP()->GetQRCodeUrl($username, $secret, 'MyApp');
// Display as a QR image using a service or JavaScript library

// Verify a code entered by the user
$code = $_POST['totp_code'];   // 6 digits
if (Security::TOTP()->Verify($secret, $code)) {
    echo "Code is valid!";
} else {
    echo "Invalid code.";
}

// Verify with a wider time drift (±2 periods, ±60 seconds)
Security::TOTP()->Verify($secret, $code, 2);

Display Name

// Get the current user's display name
echo Security::GetDisplayName();   // returns fullname, or username as fallback

// Set a custom display name in the session (temporary)
Security::SetDisplayName('John (Admin)');

Secure Token Generation

// Generate a cryptographically secure random token (hex)
$token = Security::GenerateToken();           // 64 hex chars (32 bytes)
$shortToken = Security::GenerateToken(16);    // 32 hex chars (16 bytes)
// Use for CSRF, password resets, invitation links, etc.

Auth Guards – RequireAuth, RequireRole

These are shortcut methods that immediately stop the request if the user is not authenticated or lacks the required role. They replace the repetitive guard code that was previously duplicated in every controller.

RequireAuth()

Redirects to the login page if the user is not logged in. Use it at the top of any protected method.

// Protect a whole controller method
public function listProjects(): void {
    Security::RequireAuth();
    // ... your code here
}

RequireRole(array $roles)

Stops with a 403 Forbidden message if the current user's role is not in the allowed list.

// Only superadmin and developer can create projects
Security::RequireRole(['superadmin', 'developer']);

Combined example

public function createProject(): void {
    Security::RequireAuth();
    Security::RequireRole(['superadmin', 'developer']);
    // proceed with project creation...
}

🔗 Related Help Topics

Database API Email API SMS API