Tutorial Lengkap Membuat REST API sederhana dengan JWT di CodeIgniter 4

Tutorial Lengkap Membuat REST API sederhana dengan JWT di CodeIgniter 4

Di artikel kali ini, kita bakal ngebahas gimana caranya bikin REST API pakai CodeIgniter 4 + JWT, tapi tanpa ribet pake CodeIgniter Shield. Kenapa? Soalnya kadang kita cuma butuh autentikasi yang ringan, cepat, dan gak banyak dependensi. Cocok banget buat yang bikin backend mobile, microservice, atau API sederhana buat aplikasi internal. JWT alias JSON Web Token ini udah jadi standar emas buat autentikasi modern – simpel, stateless, dan bisa dipakai lintas platform. Nah, CodeIgniter 4 sendiri belum ngasih fitur JWT out of the box, jadi kita bakal rakit sendiri dari nol biar kamu bener-bener paham alurnya. Tenang, tutorial ini step-by-step banget. Mulai dari setup project, bikin login endpoint, generate token JWT, sampai proteksi route. Cocok buat kamu yang pengen ngerti dalemannya, bukan cuma pakai.

Untuk membuat API dengan JWT di PHP, kita bisa menggunakan library dari Firebase yang bernama firebase/php-jwt. Library ini cukup populer dan memudahkan kita dalam mengelola proses encode dan decode JWT. Kalau kamu menggunakan CodeIgniter Shield, kamu tetap perlu memasang library firebase/php-jwt secara manual. Soalnya, secara default, Shield belum mendukung JWT secara bawaan—hanya sebagai fitur tambahan saja.

🚀 Panduan Lengkap

Perlu di ingat sekali lagi, pada panduan ini kita tidak akan menggunakan CodeIgniter Shield.

📦 Struktur Folder Sederhana


app/
├── Controllers/
│   ├── AuthController.php
│   └── Api/
│       └── ExampleProtectedController.php
│       └── ExampleUnprotectedController.php
├── Filters/
│   └── JwtFilter.php
├── Models/
│   └── UserModel.php
├── Database/
│   ├── Migrations/
│   └── Seeds/

1️⃣ Install Project CodeIgniter 4

Pada pembahasan ini saya menggunakan CodeIgniter 4.6.1 dan firebase/php-jwt 6.11. Jalankan perintah berikut untuk mulai membuat proyek baru CodeIgniter.


composer create-project codeigniter4/appstarter jwt-api
cd jwt-api

2️⃣ Setup Environment

Salin file .env


cp env .env

Edit file .env, lalu tambahkan beberapa baris properties berikut ini, sesuaikan saja jika memang properties sudah tersedia.


CI_ENVIRONMENT = development
app.baseURL = 'http://localhost:8080'

# JWT secret key
JWT_SECRET="rahasia_super_aman"

3️⃣ Install JWT Library

Jalankan perintah berikut untuk memasang Library JWT.


composer require firebase/php-jwt

4️⃣ Buat Tabel dan Seeder User

Migration

Buat file migration baru dengan nama CreateUsers.php lalu simpan di app/Database/Migrations.


<?php

namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class CreateUsers extends Migration
{
    public function up()
    {
        $this->forge->addField([
            'id'       => ['type' => 'INT', 'auto_increment' => true],
            'email'    => ['type' => 'VARCHAR', 'constraint' => 255],
            'password' => ['type' => 'VARCHAR', 'constraint' => 255],
            'created_at' => ['type' => 'DATETIME', 'null' => true],
            'updated_at' => ['type' => 'DATETIME', 'null' => true],
        ]);
        $this->forge->addKey('id', true);
        $this->forge->createTable('users');
    }

    public function down()
    {
        $this->forge->dropTable('users');
    }
}
?>

Model

Buat file model baru dengan nama UserModel.php lalu simpan di app/Models.


<?php

namespace App\Models;

use CodeIgniter\Model;

class UserModel extends Model
{
    protected $table = 'users';
    protected $allowedFields = ['email', 'password'];
    protected $returnType = 'array';
}
?>

Seeder (Opsional)

Buat file Seed baru dengan nama UserSeeder.php lalu simpan di app/Database/Seeds. File ini tidak wajib di buat, kamu dapat menginputkan data usernya secara manual ke Database.


<?php

namespace App\Database\Seeds;

use CodeIgniter\Database\Seeder;

class UserSeeder extends Seeder
{
    public function run()
    {
        $data = [
            'email'    => 'admin@example.com',
            'password' => password_hash('admin123', PASSWORD_DEFAULT),
        ];

        $this->db->table('users')->insert($data);
    }
}
?>

Jalankan Migration dan Seeder


php spark migrate
php spark db:seed UserSeeder

5️⃣ Buat Controller Auth untuk Login

Buat file controller baru dengan nama AuthController.php lalu simpan di app/Controllers.


<?php

namespace App\Controllers;

use CodeIgniter\RESTful\ResourceController;
use Firebase\JWT\JWT;
use App\Models\UserModel;

class AuthController extends ResourceController
{
    public function login()
    {
        $email = $this->request->getPost('email');
        $password = $this->request->getPost('password');

        $userModel = new UserModel();
        $user = $userModel->where('email', $email)->first();

        if (!$user || !password_verify($password, $user['password'])) {
            return $this->failUnauthorized('Email atau password salah.');
        }

        $key = getenv('JWT_SECRET');
        $iat = time();
        $exp = $iat + 3600; // 1 jam

        $payload = [
            'iat' => $iat,
            'exp' => $exp,
            'uid' => $user['id'],
            'email' => $user['email']
        ];

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

        return $this->respond(['token' => $token]);
    }
}
?>

6️⃣ Buat Filter untuk Cek JWT

Buat file filter baru dengan nama JwtFilter.php lalu simpan di app/Filters.


<?php

namespace App\Filters;

use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

class JwtFilter implements FilterInterface
{
    public function before(RequestInterface $request, $arguments = null)
    {
        $authHeader = $request->getHeaderLine('Authorization');
        $key = getenv('JWT_SECRET');

        if (!$authHeader || !preg_match('/Bearer\s(\S+)/', $authHeader, $matches)) {
            return response()->setJSON(['message' => 'Token tidak ditemukan'])->setStatusCode(401);
        }

        $jwt = $matches[1];

        try {
            $decoded = JWT::decode($jwt, new Key($key, 'HS256'));
            // Jika ingin gunakan data user: $request->user = $decoded;
        } catch (\Exception $e) {
            return response()->setJSON(['message' => 'Token tidak valid'])->setStatusCode(401);
        }
    }

    public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) {}
}
?>

7️⃣ Daftarkan Filter di app/Config/Filters.php


public $aliases = [
    'jwt' => \App\Filters\JwtFilter::class,
];

8️⃣ Buat Protected dan Unprotected Endpoint

Endpoint Protected hanya dapat di akses menggunakan JWT Token, sedangkan untuk Endpoint Unprotected adalah API yang bisa di akses tanpa menggunakan JWT Token.

Example Protected

Buat file controller baru dengan nama ExampleProtectedController.php lalu simpan di app/Controllers/Api.


<?php

namespace App\Controllers\Api;

use CodeIgniter\RESTful\ResourceController;

class ExampleProtectedController extends ResourceController
{
    public function index()
    {
        return $this->respond(['status' => true, 'message' => 'Protected API, Access granted, JWT valid!']);
    }
}
?>

Example Unprotected

Buat file controller baru dengan nama ExampleUnprotectedController.php lalu simpan di app/Controllers/Api.


<?php

namespace App\Controllers\Api;

use CodeIgniter\RESTful\ResourceController;

class ExampleUnprotectedController extends ResourceController
{
    public function index()
    {
        return $this->respond(['status' => true, 'message' => 'Unprotected API without JWT!']);
    }
}
?>

9️⃣ Tambahkan Route

Tambahkan route baru berikut ini pada app/Config/Routes.php


$routes->group('api', function($routes) {
    
    // Unprotected: Endpoint publik (tidak butuh token)
    $routes->post('login', 'AuthController::login');

    // Unprotected: Endpoint publik (tidak butuh token)
    $routes->get('unprotected', 'Api\ExampleUnprotectedController::index');
    
    // Protected: Endpoint yang membutuhkan JWT
    $routes->group('', ['filter' => 'jwt'], function($routes) {
        $routes->get('protected', 'Api\ExampleProtectedController::index');

        // Tambahan jika ada:
        // $routes->get('profile', 'Api\UserController::profile');
        // $routes->post('update', 'Api\UserController::update');
    });

});

✅ Uji Coba

1. Login:


POST /api/login
Content-Type: application/x-www-form-urlencoded

email=admin@example.com&password=admin123

Respon:


{
  "token": "eyJ0eXAiOiJKV1QiLCJh..."
}

2. Akses Endpoint:

Protected API


GET /api/protected
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJh...

Unprotected API


GET /api/unprotected

🚨 Tips Keamanan

  • Gunakan .env untuk JWT_SECRET (jangan hardcode) 
  • Tambahkan refresh token (opsional) 
  • Tambahkan logout dengan blacklist token (jika perlu) 
  • Gunakan HTTPS di production

Oke, cukup sampai di sini dulu pembahasan kali ini. Semoga mudah dipahami dan tentunya bermanfaat. Terima kasih 😊

full-width

0/Post a Comment/Comments

Lebih baru Lebih lama