DARMASTER LOGIN SYSTEM — Technical Documentation Daralbeida Multi-Entity Platform · 2026-06-17 ════════════════════════════════════════════════════════════════════════════════ DOCUMENT SUMMARY The DARMASTER login system provides per-user session-based authentication for protected administrative tools (Document Registry, Skin Manager). Single hardcoded user credential: pybadmin / bonjour. Session state persists across page visits, filter state auto-saves to PHP sessions, all expired sessions auto-cleanup. ════════════════════════════════════════════════════════════════════════════════ ARCHITECTURE LOGIN FLOW 1. User visits protected page (fable5_doclib.php, skin2.php) 2. Page checks $_SESSION['user_authenticated'] 3. If missing → redirect to login.php with ?redirect= 4. Login form accepts username & password 5. Credentials validated (pybadmin / bonjour only) 6. On success: $_SESSION['user_authenticated']=true, $_SESSION['username']='pybadmin' 7. Redirect back to original page (or default landing) 8. User works with filters → state auto-saved to $_SESSION['f5_filters'] 9. Click LOGOUT → destroy session → redirect to login SESSION STATE PERSISTENCE Filter state (f_status, sort, search, entity, section, etc.) is stored in $_SESSION['f5_filters'] as an associative array. On pristine page visit (no URL params), the page restores from session or applies defaults (f_status= unpublished, sort=title). After any filter change, updated values are automatically saved to session. Session expires at PHP default (~24 min); on next visit after expiry, user is logged out and sees login form. ════════════════════════════════════════════════════════════════════════════════ FILES & LOCATIONS __darmaster/login.php • Login form (POST handler) • Validates credentials (hardcoded) • Sets session vars on success • Shows error message on failure • Styled dark login UI (18x18px logo, 360px form) __darmaster/logout.php • Simple session destroyer • Calls session_destroy() • Redirects to login.php __darmaster/08/fable5_doclib.php (MODIFIED) • Added session_start() at top • Authentication check (redirects if not logged in) • Logout button (top-right corner, fixed position) • Filter state auto-restore from session • Filter state auto-save to session __darmaster/08/skin2.php (MODIFIED) • Added session_start() at top • Authentication check (identical to fable5_doclib.php) • Logout button (top-right corner, fixed position) ════════════════════════════════════════════════════════════════════════════════ IMPLEMENTATION DETAILS SESSION INITIALIZATION At the top of every protected page: if (session_status() === PHP_SESSION_NONE) session_start(); This ensures PHP session is active before any headers or auth checks. AUTHENTICATION CHECK if (empty($_SESSION['user_authenticated'])) { $login_url = preg_replace('#/08/(fable5_doclib|skin2)\.php$#', '/login.php', $_SERVER['REQUEST_URI']); header('Location: ' . $login_url . (strpos($login_url, '?') !== false ? '&' : '?') . 'redirect=' . urlencode($_SERVER['REQUEST_URI'])); exit; } Uses regex to convert current URL path to login.php path, then appends ?redirect= to allow redirect back after login. Handles existing query params correctly (& vs ?). FILTER STATE RESTORATION (FABLE5_DOCLIB.PHP) After reading GET params, page checks if ANY filter is in the URL: • If URL has filters → use those, save to session • If URL is pristine → restore from $_SESSION['f5_filters'] or use defaults • Defaults: f_status=unpublished, sort=title • Save happens after every page load: $_SESSION['f5_filters'] = [non-empty filters] LOGOUT BUTTON Fixed div at top-right (position:fixed; top:12px; right:20px; z-index:9999). Styled as simple link with border: color:#999, font-size:12px, padding:6px 12px. Points to DARMASTER_BASE . 'logout.php'. ════════════════════════════════════════════════════════════════════════════════ CREDENTIAL STORAGE Current: Hardcoded in login.php (line 14) $username === 'pybadmin' && $password === 'bonjour' Future: Can be moved to a CSV file (user_auth.csv) or database table if multi-user support is needed. No hashing implemented (dev/test only). ════════════════════════════════════════════════════════════════════════════════ SECURITY NOTES ⚠ HARDCODED CREDENTIALS — suitable for single-user dev/test only. For production: use bcrypt/argon2 hashing, store in database, implement password reset, rate-limit login attempts, add CSRF tokens. ⚠ SESSION FIXATION — standard PHP sessions are subject to fixation attacks. For production: regenerate session ID on successful login via session_regenerate_id(true). ⚠ HTTP-ONLY COOKIES — ensure PHP session cookie is HTTP-only and secure. Set in php.ini: session.cookie_httponly=1, session.cookie_secure=1 (HTTPS). ⚠ NO LOGOUT TIMER — session expires on server (~24 min), but user can stay logged in indefinitely by keeping the page open. Add idle timeout via JavaScript if needed. ════════════════════════════════════════════════════════════════════════════════ TESTING CHECKLIST ✓ Visit protected page (e.g., http://localhost/darmaster/__darmaster/08/fable5_doclib.php) ✓ Redirects to login.php ✓ Enter wrong password → shows error message "Invalid username or password." ✓ Enter correct credentials (pybadmin / bonjour) → logs in → redirects back ✓ Page loads with LOGOUT button visible (top-right) ✓ Change filters (search, status, sort) → refresh page ✓ Navigate away and return to page (same session) → filters restored ✓ Click LOGOUT → session destroyed → redirects to login ✓ Try accessing protected page after logout → back to login form ════════════════════════════════════════════════════════════════════════════════ FUTURE ENHANCEMENTS • Multi-user support (CSV or database user table) • Password hashing (bcrypt/argon2) • Session regeneration on login • Idle timeout (15–30 min) • Login attempt rate-limiting (e.g., 3 attempts per 5 min) • Audit log (log all logins/logouts with timestamp) • "Remember me" checkbox (persistent cookies) • Email/password reset (if user database exists) ════════════════════════════════════════════════════════════════════════════════ GLOSSARY SESSION — Per-user server-side storage (PHP $_SESSION), auto-managed by PHP. Persists until expiry (~24 min default) or explicit session_destroy(). PRISTINE VISIT — Page load with no filter query params in the URL. FACET — A filterable dimension (entity, section, department, status, etc.). FABLE5_DOCLIB — DARMASTER Document Registry (compact registry-only view). SKIN2 — DARMASTER Skin Manager V.2 (design editor). ════════════════════════════════════════════════════════════════════════════════ AI PROMPTS Q: How do I reset a user's password? A: Currently unsupported (hardcoded credential). To add: create user_auth.csv, implement password hashing, add a password-reset form. Reference: DARMASTER_TECH_*.txt for multi-user roadmap. Q: Can I add a second admin user? A: Yes. Modify login.php to check a user table/CSV instead of hardcoded values, implement bcrypt verification, update session to store user_id instead of username. Requires migration planning. Q: How long does a session last? A: PHP default (~24 min). Set php.ini: session.gc_maxlifetime = 1800 (30 min). User can also be logged out by manual cache clear or browser cookie deletion. Q: Is the login form protected against brute-force attacks? A: No. Production requires rate-limiting (e.g., 3 wrong attempts → 5 min lockout) and audit logging. Implement via memcache or database counter. ════════════════════════════════════════════════════════════════════════════════ REVISION HISTORY 2026-06-17 · Initial release — single hardcoded user (pybadmin / bonjour) · Session-based auth + filter state persistence · Protected pages: fable5_doclib.php, skin2.php · Logout handler + UI button ════════════════════════════════════════════════════════════════════════════════ END OF DOCUMENT