Logging in
Authentication is checking who is in front of us: the visitor enters an email and a password, the site verifies them and remembers the user in the session. CodeIgniter itself has no ready-made login. You write it yourself — it is a small controller — or install the official Shield package.
The table and the model
You need a users table with the columns id, email and password. Create a migration and a model for it, as in the database chapter:
// app/Models/UserModel.php
namespace App\Models;
use CodeIgniter\Model;
class UserModel extends Model
{
protected $table = 'users';
protected $allowedFields = ['email', 'password'];
}A password must not be stored as plain text. The database holds its hash — an irreversibly transformed string. Add the first user with a seeder:
// app/Database/Seeds/UserSeeder.php, the run() method
$this->db->table('users')->insert([
'email' => 'anna@example.com',
'password' => password_hash('secret123', PASSWORD_DEFAULT),
]);Routes
// app/Config/Routes.php
$routes->get('login', 'Auth::form');
$routes->post('login', 'Auth::login');
$routes->get('logout', 'Auth::logout');The login controller
Create the controller with php spark make:controller Auth:
// app/Controllers/Auth.php
namespace App\Controllers;
use App\Models\UserModel;
class Auth extends BaseController
{
public function form(): string
{
return view('auth/login');
}
public function login()
{
$user = model(UserModel::class)
->where('email', $this->request->getPost('email'))
->first();
$password = (string) $this->request->getPost('password');
if ($user === null || ! password_verify($password, $user['password'])) {
return redirect()->back()->with('error', 'Wrong email or password');
}
session()->regenerate();
session()->set('user_id', $user['id']);
return redirect()->to('/posts');
}
public function logout()
{
session()->destroy();
return redirect()->to('/login');
}
}password_verify() compares the entered password with the hash from the database. On success user_id is written to the session — the site recognises the user by it on the following pages.
The login form
<!-- app/Views/auth/login.php -->
<?= form_open('login') ?>
<p class="error"><?= esc(session()->getFlashdata('error')) ?></p>
<input type="email" name="email" placeholder="Email">
<input type="password" name="password" placeholder="Password">
<button type="submit">Log in</button>
<?= form_close() ?>Open /login, enter anna@example.com and secret123 — the site goes to /posts. With a wrong password the form opens again with an error message.
Protected pages and the current user
Protected addresses are guarded by the auth filter from the previous lesson: it checks user_id in the session. The data of the logged-in user is read from the database:
$user = model(UserModel::class)->find(session('user_id'));Shield
For a real project the official Shield package is the safer choice:
composer require codeigniter4/shield
php spark shield:setupThe command creates tables and settings and connects ready-made registration and login pages. It already includes password reset, user groups and permissions, and API tokens. auth()->user() returns the current user, and the session filter protects closed routes.
Common mistake
After the password is verified the session identifier must be changed; otherwise an attacker who planted a known identifier on the victim beforehand ends up in the victim's account. Call session()->regenerate() right after the password check — before writing user_id to the session.