CodeIgniter 4 RESTful APIs with JWT Authentication

Share this Article

Inside this article we will start about the development of CodeIgniter 4 RESTful APIs with JWT authentication. Inside this development steps, surely you will find very different approach from old CodeIgniter versions.

As we have seen in the previous articles of CodeIgniter 4 about it’s complete basics and it’s working MVC model. It is already different from older setups.

We are going to create APIs list for a user authentication process like Login API, Register API, Details API, Logout API with JWT. Step by step we will create CodeIgniter 4 APIs with JWT.

We will use JWT (Json Web Token) for authentication here for RESTful web services. CodeIgniter developers surely love this article. Step by step you need to work yourself as the given guide to move along with the article.

Note*: For this article, CodeIgniter v4.1 setup has been installed. May be when you are seeing, version will be updated. CodeIgniter 4.x still is in development mode.

Let’s get started.


Download & Install CodeIgniter 4 Setup

We need to download & install CodeIgniter 4 application setup to system. To set application we have multiple options to proceed. Here are the following ways to download and install CodeIgniter 4 –

  • Manual Download
  • Composer Installation
  • Clone Github repository of CodeIgniter 4

Complete introduction of CodeIgniter 4 basics – Click here to go. After going through this article you can easily download & install setup.

Here is the command to install via composer –

$ composer create-project codeigniter4/appstarter codeigniter-4

Assuming you have successfully installed application into your local system.


Settings Environment Variables

When we install CodeIgniter 4, we have env file at root. To use the environment variables means using variables at global scope we need to do env to .env

Open project in terminal

$ cp env .env

Above command will create a copy of env file to .env file. Now we are ready to use environment variables.

CodeIgniter starts up in production mode by default. Let’s do it in development mode. So that while working if we get any error then error will show up.

# CI_ENVIRONMENT = production

// Do it to 

CI_ENVIRONMENT = development

Now application is in development mode.


Create Database & Table

Need to go to PhpMyAdmin for MySQL database. Let’s create a database with the given command.

CREATE DATABASE codeigniter4_restapis;

If you wish to create this database via Manual interface of PhpMyAdmin, no worries you can also go ahead with that.

We need to create a table which stores a user data. Here is the schema of table –

CREATE TABLE `tbl_users` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(120) DEFAULT NULL,
 `email` varchar(120) DEFAULT NULL,
 `phone_no` varchar(30) DEFAULT NULL,
 `password` varchar(120) DEFAULT NULL,
 `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Again, same you can can create via Manual interface as well.

Database Connectivity with Application

Next, we need to connect the created database with codeigniter application. To configure application need to open .env file.

.env file is a environment file where we can configure database. It is in the root of the project. You can open from there.

 
#--------------------------------------------------------------------
# DATABASE
#--------------------------------------------------------------------
 database.default.hostname = localhost
 database.default.database = codeigniter4_restapis
 database.default.username = root
 database.default.password = root
 database.default.DBDriver = MySQLi
   

Now, application is successfully connected with database.


Composer – JWT Installation

For authentication, we will use Json Web Token as the security transmitter between parties.

How can we install?

For installation, very easy step via composer. Compose is a dependency manager of PHP.

Back to Terminal/Command Prompt >> Go inside Project folder >> Run Command.

$ composer require firebase/php-jwt

This command will install JWT into application. It will install jwt package into /vendor folder at project root.


Create Routes

Now, we are settings application routes. By the help of these routes we can call APIs. To setup routes we need to open the file – /app/Config/Routes.php. We have created 4 different different routes – Register, Login, Show Detail, Logout.

// .. Other routes

$routes->group("api", function ($routes) {

    $routes->post("register", "User::createUser");
    $routes->post("login", "User::validateUser");
    $routes->get("userdata", "User::userDetails");
    $routes->post("logout", "User::logoutUser");
});

Next, we need to create and work over User controller file.


Create Model

To create Model we need to go inside /app/Models and create a file inside it. File with the name of UserModel. Models are the connector between an application and with the Database Tables.

$ php spark make:model User --suffix

Open /app/Models/UserModel.php and write this code into it.

<?php

namespace App\Models;

use CodeIgniter\Model;

class UserModel extends Model
{
	protected $DBGroup              = 'default';
	protected $table                = 'tbl_users';
	protected $primaryKey           = 'id';
	protected $useAutoIncrement     = true;
	protected $insertID             = 0;
	protected $returnType           = 'array';
	protected $useSoftDelete        = false;
	protected $protectFields        = true;
	protected $allowedFields        = [
		"name", 
		"email", 
		"phone_no",
		"password"
	];

	// Dates
	protected $useTimestamps        = false;
	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          = [];
}

Create Controller

Inside this we will write all code for application controller. This code will provide the functions for APIs. Controllers are stored inside /app/Controllers. Need to create a file inside this folder named as User.php

$ php spark make:controller User

Inside this controller file we will import classes which provides functions for API development. They provide response methods for it. Class to use JWT. We will include headers at the top of the file.

Let’s create APIs methods –

Open /app/Controllers/User.php and write this code into it.

<?php

namespace App\Controllers;

use App\Models\UserModel;
use CodeIgniter\API\ResponseTrait;
use CodeIgniter\RESTful\ResourceController;
use Exception;
use \Firebase\JWT\JWT;

// headers
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=utf8");
header("Access-Control-Allow-Headers: Content-Type, Access-Control");

class User extends ResourceController
{
    use ResponseTrait;

    public function createUser()
    {
        $userModel = new UserModel();

        $data = [
            "name" => $this->request->getVar("name"),
            "email" => $this->request->getVar("email"),
            "phone_no" => $this->request->getVar("phone_no"),
            "password" => password_hash($this->request->getVar("password"), PASSWORD_DEFAULT),
        ];

        if ($userModel->insert($data)) {

            $response = [
                'status' => 200,
                "error" => FALSE,
                'messages' => 'User created',
            ];
        } else {

            $response = [
                'status' => 500,
                "error" => TRUE,
                'messages' => 'Failed to create',
            ];
        }

        return $this->respondCreated($response);
    }

    private function getKey()
    {
        return "my_application_secret";
    }

    public function validateUser()
    {
        $userModel = new UserModel();

        $userdata = $userModel->where("email", $this->request->getVar("email"))->first();

        if (!empty($userdata)) {

            if (password_verify($this->request->getVar("password"), $userdata['password'])) {

                $key = $this->getKey();

                $iat = time();
                $nbf = $iat + 10;
                $exp = $iat + 3600;

                $payload = array(
                    "iss" => "The_claim",
                    "aud" => "The_Aud",
                    "iat" => $iat,
                    "nbf" => $nbf,
                    "exp" => $exp,
                    "data" => $userdata,
                );

                $token = JWT::encode($payload, $key);

                $response = [
                    'status' => 200,
                    'error' => FALSE,
                    'messages' => 'User logged In successfully',
                    'token' => $token
                ];
                return $this->respondCreated($response);
            } else {

                $response = [
                    'status' => 500,
                    'error' => TRUE,
                    'messages' => 'Incorrect details'
                ];
                return $this->respondCreated($response);
            }
        } else {
            $response = [
                'status' => 500,
                'error' => TRUE,
                'messages' => 'User not found'
            ];
            return $this->respondCreated($response);
        }
    }

    public function userDetails()
    {
        $key = $this->getKey();
        $authHeader = $this->request->getHeader("Authorization");
        $authHeader = $authHeader->getValue();
        $token = $authHeader;

        try {
            $decoded = JWT::decode($token, $key, array("HS256"));

            if ($decoded) {

                $response = [
                    'status' => 200,
                    'error' => FALSE,
                    'messages' => 'User details',
                    'data' => $decoded
                ];
                return $this->respondCreated($response);
            }
        } catch (Exception $ex) {
            $response = [
                'status' => 401,
                'error' => TRUE,
                'messages' => 'Access denied'
            ];
            return $this->respondCreated($response);
        }
    }
}

All the methods we have now created. Need to open these configured routes inside a API testing tool. We are opening Postman to Test APIs. You can use any other tool as per your preferences.


Testing Application APIs at Postman

Open project into terminal and start development server.

$ php spark serve

REGISTER API

URL – http://localhost:8080/api/register

LOGIN API

URL – http://localhost:8080/api/login

SHOW DETAILS API

URL – http://localhost:8080/api/userdata

To learn about CodeIgniter 4 RESTful Resource controller, click here.

We hope this article helped you to learn about CodeIgniter 4 RESTful APIs with JWT Authentication in a very detailed way.

If you liked this article, then please subscribe to our YouTube Channel for PHP & it’s framework, WordPress, Node Js video tutorials. You can also find us on Twitter and Facebook.

Find More on CodeIgniter 4 here

2 thoughts on “CodeIgniter 4 RESTful APIs with JWT Authentication”

Leave a Comment