REST API Authentication Using JSON Web Tokens(JWT) In Codeigniter

Nowadays REST APIs has become the industry def facto. If you build a mobile application then you need to make some kind of API to communicate with the server for various things, like registering the user, authenticating a user or fetching the data for the application.

Codeigniter can be used to build a small to medium scale  REST API. Codeigniter does not support API building out of the box but still, you can build the API pretty easily using the Codeigniter framework

In this tutorial, I am not gonna cover how to build an API using Codeigniter instead I am gonna cover an important aspect of REST API that is the authentication technique for the RESTful API.

I am going to authenticate the incoming API request using the JSON Web Tokens(JWT) technique.

Prerequisite :

You need to have knowledge of how REST API works and knowledge of the Codeigniter framework itself.

I will use the POSTMAN software to test the API. If you don’t know what is the postman and how to use it simply googling will help you.

What is JSON Web Tokens & Why should I care?

Let’s start with the official definition of JSON Web Tokens(JWT),

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA. – Official Website

Did not understand s single word? Don’t worry let me explain you in simple terms.

A JWT token is an encrypted string which you send as a response to a client when a client tries to log in to your application.

After that on every request client makes to your API it carries that token in the header of the request. To check if the request made by the legitimate user or not you verify the token by decrypting it using the key you have initially setup.

The key is used to sign the payload . Payload is the term which refers to the data you send along with the token which generally contains user information such as UserID or email).

If the token is not from the legitimate user then the verification process of the token will fail because either the token is not signed by you or it has been tempered.

If you want to know more about the JWT then read this article written on medium.com which has done a great job of explaining the JWT,

5 Easy Steps to Understanding JSON Web Tokens (JWT)

Installations.

1). Installing the Codeigniter Framework

You can directly go to the CodeIgniter official website and download the framework or if you are familiar with composer then you can install the CodeIgniter using the following command,

> composer create-project codeigniter/framework

We require two more third-party libraries to ease our effort and we don’t have.

2). Go to this GitHub repository and download the file as zip //github.com/chriskacerguis/codeigniter-restserver

Now open that zip file and got to the application folder then now copy all the folders inside that into your project’s directory where you have installed the CodeIgniter inside into the application folder. This help he

3). Go this //github.com/ParitoshVaidya/CodeIgniter-JWT-Sample and copy these two files into the helpers folder your project.

  • authorization_helper.php
  • jwt_helper.php

These two files will help us to create and verify the JWT token.

You need a secret key.

You need to create a secret random string key which will be used by the JWT library to sign the token you want to create.

This is the feature which prevents the attacker to send the malicious token because the attacker will not be able to guess the secret key you have created.

To use this, in the production my advice will be that you use some long random string which will be hard to guess and reproduce.

Setup your secret key for token signing.

Open up the config folder of your application and create a file named jwt.php. After that put these lines in the file,

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

// Store your secret key here
// Make sure you use better, long, more random key than this
$config['jwt_key'] = 'MY_SECRET_KEY';

You have successfully set up your secret key, now you need to tell the JWT library to use this key. To do that you need to autoload the jwt.php file.

Open you autoload.php file which resides inside the config folder and add this line,

$autoload['config'] = array('jwt');

Creating The Controller.

Now you need to create a controller inside the controllers named Api.php.This controller will handle all the incoming API request in our application.

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

require APPPATH . 'third_party/REST_Controller.php';
require APPPATH . 'third_party/Format.php';

use Restserver\Libraries\REST_Controller;

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");

class Api extends REST_Controller {

    public function __construct() {
        parent::__construct();
        
        // Load these helper to create JWT tokens
        $this->load->helper(['jwt', 'authorization']); 
    }
}

/* End of file Api.php */

You can see that I have included REST_Controller.php & Format.php  from the third_party folder but you might be thinking that “Hey I have put those files in the libraries folder”.

Yes, I know that but I like to keep those files in the third_party  folder because we can’t load them as standard Codeigniter library because our controller needs to extend the REST_Controller.php to work properly hence I put those files in the third_party folder.

Now the next line tells the PHP to look for the Restserver\Libraries\REST_Controller namespace to be able to use them and extend the REST_Controller.php.

These two lines tell the browser to not to worry about the CORS error, So we can make the call to our API from any client code,

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");

Taking a Test Drive.

Let’s create a method to check if everything is working properly,

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

require APPPATH . 'third_party/REST_Controller.php';
require APPPATH . 'third_party/Format.php';

use Restserver\Libraries\REST_Controller;

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");

class Api extends REST_Controller {

    public function __construct() {
        parent::__construct();
        
        // Load these helper to create JWT tokens
        $this->load->helper(['jwt', 'authorization']);    
    }

    public function hello_get()
    {
        $tokenData = 'Hello World!';
        
        // Create a token
        $token = AUTHORIZATION::generateToken($tokenData);

        // Set HTTP status code
        $status = parent::HTTP_OK;

        // Prepare the response
        $response = ['status' => $status, 'token' => $token];

        // REST_Controller provide this method to send responses
        $this->response($response, $status);

    }

}

/* End of file Api.php */

Now open the Postman enter your URL and hit send to make the request to our API,

First Request Made In Postman

First Request Made In Postman

Creating a JWT token when user logins.

Let’s create a method which will mimic the user login,

public function login_post()
 {
        // Have dummy user details to check user credentials
        // send via postman
        $dummy_user = [
            'username' => 'Test',
            'password' => 'test'
        ];

        // Extract user data from POST request
        $username = $this->post('username');
        $password = $this->post('password');

        // Check if valid user
        if ($username === $dummy_user['username'] && $password === $dummy_user['password']) {
            
            // Create a token from the user data and send it as reponse
            $token = AUTHORIZATION::generateToken(['username' => $dummy_user['username']]);

            // Prepare the response
            $status = parent::HTTP_OK;

            $response = ['status' => $status, 'token' => $token];

            $this->response($response, $status);
        }
        else {
            $this->response(['msg' => 'Invalid username or password!'], parent::HTTP_NOT_FOUND);
        }

 }

Test this method using Postman,

Postman test result for login method

Postman test result for login method

 

How to use the token to verify the user request.

You have learned that how you can create the JWT token and send it as the response when user login. Now you are wondering that How I can use that to verify any incoming request to my API. Don’t worry got you covered.

So you store that token at client side and every time a user wants to make a request to some protected and private API endpoint you send that token in the header of the request.

We generally use the Authorization header type to send that token to the server side processing. You can also send that token with the normal POST request but it is a general practice to send JWT token in the headers.

Creating a method to verify the incoming user request.

private function verify_request()
{
    // Get all the headers
    $headers = $this->input->request_headers();

    // Extract the token
    $token = $headers['Authorization'];

    // Use try-catch
    // JWT library throws exception if the token is not valid
    try {
        // Validate the token
        // Successfull validation will return the decoded user data else returns false
        $data = AUTHORIZATION::validateToken($token);
        if ($data === false) {
            $status = parent::HTTP_UNAUTHORIZED;
            $response = ['status' => $status, 'msg' => 'Unauthorized Access!'];
            $this->response($response, $status);

            exit();
        } else {
            return $data;
        }
    } catch (Exception $e) {
        // Token is invalid
        // Send the unathorized access message
        $status = parent::HTTP_UNAUTHORIZED;
        $response = ['status' => $status, 'msg' => 'Unauthorized Access! '];
        $this->response($response, $status);
    }
}

Testing the method.

Now I have created a method to check the validity of any incoming user request. You can use this method at the beginning of any method if you want to restrict the access for the public user and allow only logged in users.

Let’s create a dummy method to test if this works,

public function get_me_data_post()
{
    // Call the verification method and store the return value in the variable
    $data = $this->verify_request();

    // Send the return data as reponse
    $status = parent::HTTP_OK;

    $response = ['status' => $status, 'data' => $data];

    $this->response($response, $status);
}

Test this method using the postman software. You have to copy the token which to get from the login request and paste in the header section of Postman like shown in the below picture.

incoming request verification

incoming request verification

Tempering with the token value.

Now you try to temper with the token generated by the login method. You can add/remove any character from the token. Now if you try to send that tempered token in the Authorization header you will get the following error,

Sending invalid token

Sending invalid token

If you have any suggestions or if you face any problem please write it down in the comment box…

Happy Coding…:)

Click Here To Download Complete Project Files

PHP traits – Everything you need to know

Ropali Munshi
Ropali Munshi
Ropali Munshi is fullstack PHP Developer. He is passionate developer who loves to learn and expirement with new programming languages , libraries and frameworks. Nowdays he is more into the JavaScript realm.

Leave a Reply

Your email address will not be published. Required fields are marked *