Publié le : 24/01/2023

Codeigniter 4 RESTful API authentification en utilisant JWT

Nous allons donner quelques définitions avant de parler de l’authentification en utilisant le REST API de Codeigniter 4 et JWT.

Tout d’abord, nous allons définir ce que c’est le JWT. Le JWT signifie « JSON Web Token », c’est un standard ouvert (RFC 7519) qui définit une manière compacte et autonome de transmettre de manière sécurisée des informations entre les parties sous forme d’objets JSON. JWT est généralement utilisé pour l’autorisation, l’échange d’informations et d’autres applications.

Ensuite, nous avons un article dédié à l’API REST qui décrit en détail comment il fonctionne.

Maintenant revenons à nos moutons qui est : de s’authentifier avec le REST API de Codeigniter 4 et le JWT.

Mais avant, il faut dire ici que nous avons déjà une base de données qui contient une table d’utilisateur. Cette table d’utilisateur contient trois colonnes à savoir :

  • id de type entier : il contient l’identifiant de l’utilisateur ;
  • login de type varchar : qui va contenir le login de l’utilisateur;
  • password de type varchar : qui va contenir son mot de passe.

Etape préalable avant de mettre en place l’authentification sous Codeigniter 4 en utilisant le REST API et JWT

Installer Codeigniter 4

Tout d’abord, il faut installer Codeigniter 4.

A titre de rappel, l’installation de Codeigniter 4 se fait via composer en utilisant la commande :

composer create-project codeigniter4/appstarter ci-4-jwt

Configuration de Codeigniter 4

Une fois l’installation faite, nous allons configurer Codeigniter pour pouvoir communiquer avec la base de données. Pour ce faire, nous allons modifier le fichier .env comme suit :

database.default.hostname = localhost
database.default.database = database
database.default.username = root
database.default.password = password
database.default.DBDriver = MySQLi
database.default.DBPrefix = prefix_

Création du modèle

Ensuite, nous allons créer le modèle UtilisateurModel un modèle Codeigniter pour le modèle de l’utilisateur.

Pour le créer, on peut soit utiliser la commande :

php spark make:model UtilisateurModel

Soit créer directement le fichier UtilisateurModel.php dans le répertoire Models dans le répertoire app.

Et à l’intérieur du fichier UtilisateurModel.php, nous aurons le code ci-dessous :

<?php
  
namespace App\Models;
  
use CodeIgniter\Model;
  
class UtilisateurModel extends Model
{
    protected $DBGroup              = 'default';
    protected $table                = 'users';
    protected $primaryKey           = 'id';
    protected $useAutoIncrement     = true;
    protected $insertID             = 0;
    protected $returnType           = 'array';
    protected $useSoftDeletes       = false;
    protected $protectFields        = true;
    protected $allowedFields        = ['login', 'password'];
  
    // Dates
    protected $useTimestamps        = true;
    protected $dateFormat           = 'datetime';
    protected $createdField         = 'created_at';
    protected $updatedField         = 'updated_at';
    protected $deletedField         = 'deleted_at';
  
    // Validation
    protected $validationRules      = [];
    protected $validationMessages   = [];
    protected $skipValidation       = false;
    protected $cleanValidationRules = true;
  
    // Callbacks
    protected $allowCallbacks       = true;
    protected $beforeInsert         = [];
    protected $afterInsert          = [];
    protected $beforeUpdate         = [];
    protected $afterUpdate          = [];
    protected $beforeFind           = [];
    protected $afterFind            = [];
    protected $beforeDelete         = [];
    protected $afterDelete          = [];
}

Installation et configuration de JWT

Pour l’installation de JWT sous PHP, nous allons utiliser Composer. La commande d’installation est la suivante :

composer require firebase/php-jwt

Une fois faite, nous allons revenir vers le fichier .env pour ajouter la clé JWT :

#--------------------------------------------------------------------
# JWT
#--------------------------------------------------------------------
JWT_SECRET = 'JWT SECRET KEY SAMPLE HERE'

Création du controller de Codeigniter 4 pour l’authentification avec le REST API et JWT

Comme pour le Model que l’on a vu un peut plus haut, le controller, dans Codeigniter 4 peut être créé via une commande :

php spark make:controller Login

On peut aussi directement créer un fichier Login.php sous le répertoire Controllers du répertoire app.

Le contenu de ce fichier sera :

<?php
 
namespace App\Controllers;
 
use CodeIgniter\API\ResponseTrait;
use App\Models\UserModel;
use CodeIgniter\RESTful\ResourceController;
use \Firebase\JWT\JWT;
 
class Login extends ResourceController
{
    use ResponseTrait;
     
    public function index()
    {
        $utilisateurModel = new UtilisateurModel();
  
        $login = $this->request->getVar('login');
        $password = $this->request->getVar('password');
        $user = $userModel->where('login', $login)->first();
  
        if(is_null($user)) {
            return $this->respond(['error' => 'Invalid username or password.'], 401);
        }
  
        $pwd_verify = password_verify($password, $user['password']);
  
        if(!$pwd_verify) {
            return $this->respond(['error' => 'Invalid username or password.'], 401);
        }
 
        $key = getenv('JWT_SECRET');
        $iat = time(); // current timestamp value
        $exp = $iat + ( 24 * 3600 );
 
        $payload = array(
            "iss" => "Issuer of the JWT",
            "aud" => "Audience that the JWT",
            "sub" => "Subject of the JWT",
            "iat" => $iat, //Time the JWT issued at
            "exp" => $exp, // Expiration time of token
            "login" => $user['login'],
        );
         
        $token = JWT::encode($payload, $key, 'HS256');
 
        $response = [
            'message' => 'Login Succesful',
            'token' => $token
        ];
         
        return $this->respond($response, 200);
    }
 
}

Création du Controller Filter

Le Controller Filter est une classe Codeigniter 4 qui permet d’exécuter une action avant ou après qu’il soit exécuter.

Nous allons, de ce fait, créer un filtre qui sera utiliser pour vérifier si la requête soit permit et ait l’autorisation. Ainsi, nous allons exécuter la commande ci-dessous pour créer le Controller Filter :

php spark make:filter AuthFilter

Nous pouvons aussi créer directement le fichier AuthFilter.php dans le répertoire Filters du répertoire app.

Le contenu de ce fichier sera alors :

<?php
 
namespace App\Filters;
 
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
 
class AuthFilter implements FilterInterface
{
    
    /**
     * Do whatever processing this filter needs to do.
     * By default it should not return anything during
     * normal execution. However, when an abnormal state
     * is found, it should return an instance of
     * CodeIgniter\HTTP\Response. If it does, script
     * execution will end and that Response will be
     * sent back to the client, allowing for error pages,
     * redirects, etc.
     *
     * @param RequestInterface $request
     * @param array|null       $arguments
     *
     * @return mixed
     */
    public function before(RequestInterface $request, $arguments = null)
    {
        $key = getenv('JWT_SECRET');
        $header = $request->getHeader("Authorization");
        $token = null;
  
        // extract the token from the header
        if(!empty($header)) {
            if (preg_match('/Bearer\s(\S+)/', $header, $matches)) {
                $token = $matches[1];
            }
        }
  
        // check if token is null or empty
        if(is_null($token) || empty($token)) {
            $response = service('response');
            $response->setBody('Access denied');
            $response->setStatusCode(401);
            return $response;
        }
  
        try {
            $decoded = JWT::decode($token, new Key($key, 'HS256'));
        } catch (Exception $ex) {
            $response = service('response');
            $response->setBody('Access denied');
            $response->setStatusCode(401);
            return $response;
        }
    }
  
    /**
     * Allows After filters to inspect and modify the response
     * object as needed. This method does not allow any way
     * to stop execution of other after filters, short of
     * throwing an Exception or Error.
     *
     * @param RequestInterface  $request
     * @param ResponseInterface $response
     * @param array|null        $arguments
     *
     * @return mixed
     */
    public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
    {
        //
    }
}

Après que ce controlleur ait été créé, nous allons configurer dans le répertoire Config du répertoire app le fichier Filters.php, et nous allons ajouter :

<?php
 
namespace Config;
 
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Filters\CSRF;
use CodeIgniter\Filters\DebugToolbar;
use CodeIgniter\Filters\Honeypot;
 
class Filters extends BaseConfig
{
    /**
     * Configures aliases for Filter classes to
     * make reading things nicer and simpler.
     *
     * @var array
     */
    public $aliases = [
        'csrf'     => CSRF::class,
        'toolbar'  => DebugToolbar::class,
        'honeypot' => Honeypot::class,
        'authFilter' => \App\Filters\AuthFilter::class,
    ];
 
    /**
     * List of filter aliases that are always
     * applied before and after every request.
     *
     * @var array
     */
    public $globals = [
        'before' => [
            // 'honeypot',
            // 'csrf',
        ],
        'after'  => [
            'toolbar',
            // 'honeypot',
        ],
    ];
 
    /**
     * List of filter aliases that works on a
     * particular HTTP method (GET, POST, etc.).
     *
     * Example:
     * 'post' => ['csrf', 'throttle']
     *
     * @var array
     */
    public $methods = [];
 
    /**
     * List of filter aliases that should run on any
     * before or after URI patterns.
     *
     * Example:
     * 'isLoggedIn' => ['before' => ['account/*', 'profiles/*']]
     *
     * @var array
     */
    public $filters = [];
}

Enregistrement des routes REST API de Codeigniter 4 pour l’authentification avec JWT

Pour les routes de Codeigniter 4, nous allons modifier le fichier Routes.php du répertoire Config du répertoire app.

Nous ajouterons alors le contenu ci-dessous :

$routes->post("login", "Login::index");
$routes->resource('type',['filter' => 'authFilter']);

Donnons un peu d’explication sur ce code PHP.

Tout d’abord, la première ligne va permettre d’accéder à l’URL /login. Et cet URL sera pointer vers la méthode index du controlleur Login.

Ensuite, la deuxième ligne va vérifier si la personne qui accède à l’URL /type a tous les droits. C’est à dire si la personne est authentifié. Cette authentification est faite par la classe AuthFilter définit un peu plus haut.

Test du résultat d’authentification

Pour le test du résultat d’authentification, nous allons utiliser l’outil Postman. Cet outil peut être télécharger via l’URL : https://www.postman.com/downloads/

En exécutant l’URL http://localhost:14080/api/login?login=a@a.com&password=abcd sur un environnement de développement nous avons le résultat suivant :

Les mots clés rattachés à cet article : Codeigniter  -  JWT  -  Rest api

Nos clients

Une vingtaine de clients nationaux et internationaux