The Auth class handles all authentication for your application. It supports two independent actor types — admin and user — each with their own session, login flow, and remember-me cookie. Both can be logged in simultaneously without conflict.
- Class:
JiFramework\Core\Auth\Auth - Access via:
$app->auth
Features:
- Email + password login with
password_verify()(bcrypt-safe) - Login by ID for internal or OAuth flows
- Remember me tokens stored in database, valid for 30 days
- Token cookies are
HttpOnlyandSecure - Automatic token check on every
new App()— users are restored from cookie transparently - Configurable table names — no hardcoded schema requirements
Auth requires three database tables. Create them with the following schema:
-- Admin accounts
CREATE TABLE admin (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(180) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL
);
-- User accounts
CREATE TABLE users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(180) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL
);
-- Remember-me tokens (shared by both admins and users)
CREATE TABLE tokens (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id INT UNSIGNED NOT NULL,
token VARCHAR(64) NOT NULL UNIQUE,
expire_datetime DATETIME NOT NULL,
type ENUM('admin', 'user') NOT NULL
);
You can add any extra columns you need (e.g. name, status, created_at) — Auth only reads id, email, and password internally.
Always store passwords as bcrypt hashes:
$hash = password_hash('plain_password', PASSWORD_BCRYPT);
Table names and session keys are fully configurable. Add any of these to config/jiconfig.php:
return [
// Table names (defaults shown)
'auth_admin_table' => 'admin',
'auth_user_table' => 'users',
'auth_token_table' => 'tokens',
// Session keys (defaults shown)
'session_admin_key' => 'admin',
'session_user_key' => 'user',
];
These map to Config::$authAdminTable, Config::$authUserTable, Config::$authTokenTable, Config::$adminSessionKey, and Config::$userSessionKey. Changing them does not require touching framework code.
adminLogin(string $email, string $password, bool $remember = false): bool
Verifies credentials against the admin table. On success, stores the admin ID in the session. Returns true on success, false on failure.
$email— (string) Admin email address$password— (string) Plain-text password to verify against the stored hash$remember— (bool, optional) Set totrueto issue a 30-day remember-me cookie. Default:false
// Basic login
if ($app->auth->adminLogin($_POST['email'], $_POST['password'])) {
$app->redirect('/admin/dashboard');
} else {
$error = 'Invalid email or password.';
}
// Login with remember me
$remember = isset($_POST['remember']) && $_POST['remember'] === '1';
if ($app->auth->adminLogin($_POST['email'], $_POST['password'], $remember)) {
$app->redirect('/admin/dashboard');
}
userLogin(string $email, string $password, bool $remember = false): bool
Identical to adminLogin() but operates on the user table and user session key.
$email— (string) User email address$password— (string) Plain-text password$remember— (bool, optional) Issue a 30-day remember-me cookie. Default:false
if ($app->auth->userLogin($_POST['email'], $_POST['password'])) {
$app->redirect('/dashboard');
} else {
$error = 'Invalid credentials.';
}
adminLoginById(int $id): bool
userLoginById(int $id): bool
Logs in an admin or user by their database ID, skipping password verification. Useful for OAuth callbacks, impersonation, or automatic login after registration.
$id— (int) The primary key of the admin or user record
// Log in a user immediately after registration
$userId = $app->db->table('users')->insertGetId([
'email' => $_POST['email'],
'password' => password_hash($_POST['password'], PASSWORD_BCRYPT),
]);
$app->auth->userLoginById($userId);
$app->redirect('/dashboard');
// OAuth callback: find or create user, then log them in
$user = $app->db->table('users')->where('email', $oauthEmail)->first();
if (!$user) {
$id = $app->db->table('users')->insertGetId(['email' => $oauthEmail, 'password' => '']);
} else {
$id = $user['id'];
}
$app->auth->userLoginById($id);
$app->redirect('/dashboard');
adminLogout(): void
userLogout(): void
Destroys the session entry, deletes the remember-me token from the database, and expires the remember-me cookie. Call these on logout endpoints.
// Admin logout
$app->auth->adminLogout();
$app->redirect('/admin/login');
// User logout
$app->auth->userLogout();
$app->redirect('/login');
// Combined logout (log out both at once if needed)
$app->auth->adminLogout();
$app->auth->userLogout();
$app->redirect('/');
isAdminLoggedIn(): bool
isUserLoggedIn(): bool
Returns true if the respective actor has an active session. Use these as guards at the top of protected pages.
// Guard an admin page
if (!$app->auth->isAdminLoggedIn()) {
$app->redirect('/admin/login');
}
// Guard a user page
if (!$app->auth->isUserLoggedIn()) {
$app->redirect('/login');
}
// Check both independently
if ($app->auth->isAdminLoggedIn() && $app->auth->isUserLoggedIn()) {
// Edge case: someone is logged in as both admin and user simultaneously
}
Because remember-me tokens are checked automatically when $app->auth is first accessed, a user who closed the browser but has a valid cookie will appear as logged in immediately — no extra code needed.
getAdminId(): int|null
getUserId(): int|null
Returns the primary key of the currently authenticated admin or user. Returns null if not logged in.
$adminId = $app->auth->getAdminId(); // e.g. 1 or null
$userId = $app->auth->getUserId(); // e.g. 42 or null
// Typical usage: fetch logged-in user data
$userId = $app->auth->getUserId();
if ($userId) {
$posts = $app->db->table('posts')
->where('user_id', $userId)
->orderBy('created_at', 'DESC')
->get();
}
getAdmin(): array|null
getUser(): array|null
Fetches the full database row of the currently authenticated admin or user. Returns the row as an associative array, or null if not logged in.
// Get logged-in user details
$user = $app->auth->getUser();
if ($user) {
echo 'Welcome, ' . htmlspecialchars($user['name']);
}
// Get logged-in admin details
$admin = $app->auth->getAdmin();
if ($admin) {
echo 'Logged in as admin: ' . htmlspecialchars($admin['email']);
}
// Safe access with null check
$name = $app->auth->getUser()['name'] ?? 'Guest';
This performs a database query on every call. If you need the user data multiple times in one request, assign it to a variable.
clearExpiredTokens(): void
Deletes all expired remember-me tokens from the tokens table. This is a maintenance method — the framework does not call it automatically. Run it periodically to keep the tokens table lean.
// Call from a scheduled script or cron job
$app->auth->clearExpiredTokens();
// Or call it on a low-frequency page to do light maintenance
// (e.g. once every 100 requests using a random check)
if (rand(1, 100) === 1) {
$app->auth->clearExpiredTokens();
}
A complete login page handling both GET (show form) and POST (process login) in a single file:
<?php
require __DIR__ . '/vendor/autoload.php';
$app = new App();
// Already logged in - send to dashboard
if ($app->auth->isUserLoggedIn()) {
$app->redirect('/dashboard');
}
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Validate input first
$valid = $app->validator->validate($_POST, [
'email' => 'required|email',
'password' => 'required',
]);
if (!$valid) {
$error = 'Please enter a valid email and password.';
} else {
$remember = !empty($_POST['remember']);
if ($app->auth->userLogin($_POST['email'], $_POST['password'], $remember)) {
$app->logger->info('User logged in', ['user_id' => $app->auth->getUserId()]);
$app->redirect('/dashboard');
} else {
$error = 'Incorrect email or password.';
}
}
}
?>
<!DOCTYPE html>
<html>
<body>
<form method="POST">
<?php if ($error): ?>
<p style="color:red"><?= htmlspecialchars($error) ?></p>
<?php endif ?>
<input type="email" name="email" placeholder="Email" required>
<input type="password" name="password" placeholder="Password" required>
<label><input type="checkbox" name="remember" value="1"> Remember me</label>
<button type="submit">Login</button>
</form>
</body>
</html>
A protected admin panel page that guards access, shows the logged-in user, and handles logout:
<?php
require __DIR__ . '/vendor/autoload.php';
$app = new App();
// Guard: redirect if not logged in
if (!$app->auth->isAdminLoggedIn()) {
$app->redirect('/admin/login');
}
// Handle logout
if (isset($_GET['logout'])) {
$app->auth->adminLogout();
$app->redirect('/admin/login');
}
// Fetch current admin and their stats
$admin = $app->auth->getAdmin();
$totalUsers = $app->db->table('users')->count();
$newToday = $app->db->table('users')
->where('created_at', '>=', date('Y-m-d') . ' 00:00:00')
->count();
?>
<!DOCTYPE html>
<html>
<body>
<h1>Admin Dashboard</h1>
<p>Welcome, <?= htmlspecialchars($admin['email']) ?></p>
<p>Total users: <?= $totalUsers ?> | New today: <?= $newToday ?></p>
<a href="?logout=1">Logout</a>
</body>
</html>