Extending Authentication

Lightpack's authentication system is made up of two key building blocks: Authenticators and Identifiers.

Understanding how these work together will help you confidently customize authentication for your application.

Concepts

Authenticator

Identifier

How do they work together?

When do you need a custom Identifier?

Why this separation?

Below we document in detail how to define your own custom authenticators and identifiers as required.

Authenticators

Authenticators are classes that extend Lightpack\Auth\Authenticator class.

These classes are responsible for authenticating a request. You can create your own authenticator by extending this class. For example:

class JwtAuthenticator extends Authenticator
{
    public function verify(): ?IdentityInterface
    {
        // custom auth logic goes here
    }
}

The verify() method should return an instance of \Lightpack\Auth\IdentityInterface (or null if authentication fails).

To use your custom authenticator, you should register it using the extend() method. For example, in your login controller:

class LoginController
{
    public function authenticate()
    {
        // Register custom authenticator
        auth()->extend('jwt', JwtAuthenticator::class);

        // Use it
        $user = auth()->attempt();

        if (!$user) {
            return redirect()->to('login');
        }

        return redirect()->intendedRoute('dashboard');
    }
}

Identifiers

Identifiers are classes that implement Lightpack\Auth\IdentifierInterface interface.

These classes are responsible for fetching users and they act as user repository or user data service providers. You can create your own identifier by implementing this interface. For example:

class CustomIdentifier implements IdentifierInterface
{
    public function findById($id): ?IdentityInterface
    {
        // custom logic to fetch user by id
    }

    public function findByRememberToken($id, string $token): ?IdentityInterface
    {
        // fetch user with matching remember_me token
    }

    public function findByCredentials(array $credentials): ?IdentityInterface
    {
        // fetch user by username/password credentials
    }

    public function updateLogin($id, array $fields)
    {
        // update login fields 
    }
}

Configuration

Configure your custom identifier in config/auth.php:

return [
    'auth' => [
        'drivers' => [
            'default' => [
                // ...
            ],
            'custom' => [
                'model' => App\Models\User::class,
                'identifier' => CustomIdentifier::class,
                'remember_duration' => 60 * 24 * 30,
            ],
        ],
        'routes' => [
            'login' => 'login',
            'home' => 'dashboard',
        ],
    ],
];

To use your custom driver, call setDriver() before authentication:

namespace App\Controllers;

class LoginController
{
    public function authenticate()
    {
        $user = auth('custom')->attempt();

        if (!$user) {
            session()->flash('error', 'Invalid credentials.');
            return redirect()->to('login');
        }

        return redirect()->intendedRoute('dashboard');
    }
}

Quick Summary

Component Purpose How to Customize
Authenticator Verifies requests (JWT, OAuth, etc.) Extend Authenticator, register with extend()
Identifier Fetches users from data source Implement IdentifierInterface interface, add to config
Driver Combines model + identifier + config Add new driver in config/auth.php

Default Setup: