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 😊
Posting Komentar