Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

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:setup

The 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.

Thanks for reading!

Donate to the site — we work hard for you.