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

Nowadays REST APIs has become the industry de 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 to write everything from scratch.

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. 

The above library has changed to support PHP 7.2 & latest version of CI, So if you are still using the PHP 5 then Follow these instructions to get the old version of that library. If you are using the latest PHP 7.2 (Which is recommended) then you can go to the above Github link to find the instructions for usage else follow this,

1).  Create a file in your third_party directory named REST_Controller.php & now go to this gist link, copy all the code & paste it in the REST_Controller.php.

2).  Create a file in your third_party directory named Format.php & now go to this gist link, copy all the code & paste it in the Format.php.

3). Create a file inside the config directory named rest.php & now go to this gist link , copy all the code & paste it inside the res.php file.

This is good to go now…

3). Go to this link //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.

36 Comments

  1. Good article, helped me, thanks!

  2. Maiara says:

    Ohhh nice! i’am a developer jr. and stay learning jwt and this article is very good! Thanks man

  3. Jignesh says:

    Where are the JWT tokens stored on back-end side to get verified? Or how token verification process occurs?

    • Ropali Munshi says:

      You don’t actually need to store the tokens. You put the data inside the token which are already stored in your database like user_id. When you receive the token at server side you just need to verify the authenticity of the token which is done by the library using encryption/decryption methods.

      • Jignesh says:

        Okay so you mean to say that token gets decrypted and user_name gets verified? Then where is the code to verify decrypted user_name against user_name stored in database?

        • Ropali Munshi says:

          user_name is stored in your database & you verify the user_name against your database. Hope this clears your doubt…

  4. gr says:

    thanks for your work, but I have an error when I send my request to Postman
    http://localhost/CodeIgniterApi/api/hello
    Fatal error: Class Api cannot extend from trait Restserver\Libraries\REST_Controller in on line 10, my line 10 is :
    class Api extends REST_Controller

    have you an idea how to fix that?

    best regards

    • Ropali Munshi says:

      You might want to check if it is properly imported in the file.

    • david says:

      I had the same error, i donwload the file of this example, when i compare it with the instructions i noticed that GitHub repository file zip //github.com/chriskacerguis/codeigniter-restserver chang are not the same, maybe something changed in the controller folder, try it to download this complete project files. ( sorry for my bad english )

  5. satrio says:

    in folder third_party i don’t have file with name format.php, i try this tutorial i have a error
    CodeIgniter-JWT-Sample\application\third_party/Format.php

    have you an idea how to fix that?

  6. Jewel Rana says:

    How to revoke the token, if session expired or user logout?
    Thanks for nice article.

    • Ropali Munshi says:

      you can set the token_timeout value in the config file.When a user sends a request you can also validate the timestamp to the sent token using the validateTimestamp() method by passing the token value in it with some auto token renewal mechanism. Hope this answers your question.

  7. dede hermawan says:

    with postman for acess http://localhost/ci-api-auth/index.php/api/get_me_data with Authorization header was work

    but if i want access get_me_data use curl in terminal,
    i’m used script belowd:
    curl -H “Authorization: ” http://localhost/ci-api-auth/index.php/api/get_me_data

    but the result status is 401

  8. dede hermawan says:

    sorry my bad,, the issue was solved i have some wrong on config jwt.php
    thanks for your article, nice article

  9. sanket says:

    Thanks for helping me out.

  10. Mas'ud says:

    I’ve little project, my question is, “Can I get detail user data using JWT when I was login?”, (exmple : on client-side detail user data can showing), thanks before

    • Ropali Munshi says:

      Yes, you can decode the token to get the user details at the client-side but to authenticate the token you need the secret key & it is not recommended to store your secret key in the frontend due to security reasons…

      • Mas'ud says:

        Thanks Ropali for your answer, that’s important for me and I’ve one question again, when user was log in, may user get detail from other table was join from table user ? (example : user get he data buying from table buy on join table)

  11. HungVan says:

    Good article, I’m looking into this issue.

  12. ramdan says:

    how to invalidate the token ?

  13. How to work on same project using JWT with private key ?

  14. Thank you a million times over.

  15. Ficky Fadly says:

    Nice article, very helpful!! thanks a lot for u 🙂

  16. Zero says:

    Nice shared, I wonder if I can make that function token as library.?

    //call function create_token from library.
    $token = $this->create_token($foo);

    I tried put on library but the session is error.
    Unable to locate the specified class: Session.php

  17. MAnisha says:

    Thank you very much ..its very helpfull

Leave a Reply

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