Sobatcoding.com - Tutorial Membuat REST API Codeigniter 4 Menggunakan JWT Auth
Kali ini kita kan mencoba membuat REST API menggunakan Codeigniter 4 dan JWT Auth. Berikut langsung saja langkah-langkahnya.
Langkah pertama kita install terlebih dahulu codeigniter 4 menggunakan composer, jalankan command beriktu di terminal kalian :
composer create-project codeigniter4/appstarter ci4restapi
Setelah proses install selesai kita setup terlebih dahulu config dan koneksi ke database nya.
Copy file env dan paste kemudian rename menjadi .env, lalu ubah beberapa kode di line berikut:
#--------------------------------------------------------------------
# ENVIRONMENT
#--------------------------------------------------------------------
CI_ENVIRONMENT = development
#--------------------------------------------------------------------
# APP
#--------------------------------------------------------------------
app.baseURL = 'http://localhost:8080/'
Setup juga untuk koneksi database di line berikut.
#--------------------------------------------------------------------
# DATABASE
#--------------------------------------------------------------------
database.default.hostname = 'localhost'
database.default.database = 'rest_api'
database.default.username = 'root'
database.default.password =
database.default.DBDriver = 'MySQLi'
Buat sebuah model bernama Users.php di folder App\Models dan masukkan kode berikut.
<?php
namespace App\Models;
use CodeIgniter\Model;
class Users extends Model
{
protected $DBGroup = 'default';
protected $table = 'm_users';
protected $primaryKey = 'id';
protected $useAutoIncrement = true;
protected $insertID = 0;
protected $returnType = 'array';
protected $useSoftDelete = false;
protected $protectFields = true;
protected $allowedFields = ['username', 'password', 'name', 'addrress', 'phone'];
// Dates
protected $useTimestamps = true;
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 = [];
}
Kalian juga bisa generate file ini secara otomatis mengunakan perintah php spark make:model Users
di terminal kalian.
Buatlah sebuah controller bernama UserController.php di folder App\Controllers\Api dan masukkan kode berikut.
<?php
namespace App\Controllers\Api;
use App\Controllers\BaseController;
use App\Models\Users;
use CodeIgniter\API\ResponseTrait;
class UserController extends BaseController
{
use ResponseTrait;
public function index()
{
$db = new Users;
$user = $db->get()->getResult();
return $this->response->setJSON( ['sucess'=> true, 'mesage' => 'OK', 'data' => $user] );
}
public function create()
{
if( !$this->validate([
'username' => 'required|is_unique[m_users.username]',
'password' => 'required|min_length[6]',
'name' => 'required',
'address' => 'required',
'phone' => 'required'
]))
{
return $this->response->setJSON(['success' => false, 'data' => null, "message" => \Config\Services::validation()->getErrors()]);
}
$insert = [
'username' => $this->request->getVar('username'),
'password' => password_hash($this->request->getVar('password'), PASSWORD_DEFAULT),
'name' => $this->request->getVar('name'),
'naaddressme' => $this->request->getVar('address'),
'phone' => $this->request->getVar('phone'),
];
$db = new Users;
$save = $db->insert($insert);
return $this->setResponseFormat('json')->respondCreated( ['sucess'=> true, 'mesage' => 'OK'] );
}
public function show($id)
{
$db = new Users;
$user = $db->where('id', $id)->first();
return $this->response->setJSON( ['sucess'=> true, 'mesage' => 'OK', 'data' => $user] );
}
public function update($id)
{
if (! $this->validate([
'username' => 'permit_empty|is_unique[m_users.username,id,'.$id.']',
'password' => 'permit_empty|min_length[6]',
'name' => 'permit_empty',
'address' => 'permit_empty',
'phone' => 'permit_empty',
])) {
return $this->response->setJSON(['success' => false, "message" => \Config\Services::validation()->getErrors()]);
}
$db = new Users;
$exist = $db->where('id', $id)->first();
if( !$exist )
{
return $this->response->setJSON(['success' => false, "message" => 'User not found']);
}
$update = [
'username' => $this->request->getVar('username') ? $this->request->getVar('username') : $exist['username'],
'password' => $this->request->getVar('password') ? password_hash($this->request->getVar('password'), PASSWORD_DEFAULT) : $exist['password'],
'name' => $this->request->getVar('name') ? $this->request->getVar('name') : $exist['name'],
'naaddressme' => $this->request->getVar('address') ? $this->request->getVar('address') : $exist['address'],
'phone' => $this->request->getVar('phone') ? $this->request->getVar('phone') : $exist['phone']
];
$db = new Users;
$save = $db->update( $id, $update);
return $this->response->setJSON(['success' => true,'message' => 'OK']);
}
public function delete($id)
{
$db = new Users;
$db->where('id', $id);
$db->delete();
return $this->response->setJSON( ['sucess'=> true, 'mesage' => 'OK'] );
}
}
Kalian juga bisa generate file ini secara otomatis mengunakan perintah php spark make:controller Api\UserController
di terminal kalian.
Buat juga controller untuk handle waktu user login, karena saat login inilah waktu kita generate token pertama kali. Buat controller bernama AuthController.php dan masukkan kode berikut.
<?php
namespace App\Controllers;
use App\Controllers\BaseController;
use App\Models\Users;
use App\Libraries\JWTCI4;
class AuthController extends BaseController
{
public function login()
{
if( !$this->validate([
'username' => 'required',
'password' => 'required|min_length[6]',
]))
{
return $this->response->setJSON(['success' => false, 'data' => null, "message" => \Config\Services::validation()->getErrors()]);
}
$db = new Users;
$user = $db->where('username', $this->request->getVar('username'))->first();
if( $user )
{
if( password_verify($this->request->getVar('password'), $user['password']) )
{
$jwt = new JWTCI4;
$token = $jwt->token();
return $this->response->setJSON( ['token'=> $token ] );
}
}else{
return $this->response->setJSON( ['success'=> false, 'message' => 'User not found' ] )->setStatusCode(409);
}
}
}
Buatlah sebuah filter bernama CorsFilter.php dengan command php spark make:filter CorsFilter
di terminal kalian. Kemudian masukkan kode berikut di dalam function before.
* @return mixed
*/
public function before(RequestInterface $request, $arguments = null)
{
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Max-Age: 86400");
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Authorization");
if ( $request->getMethod() == 'options')
{
$response = service('response');
$response->setJSON(['method' => 'OPTIONS']);
return $response;
die();
}
}
Langkah selanjutnya adalah register filter tersebut dengan cara buka file App\Config\Filters.php, dan masukkan kode seperti berikut.
/**
* Configures aliases for Filter classes to
* make reading things nicer and simpler.
*
* @var array
*/
public $aliases = [
'csrf' => CSRF::class,
'toolbar' => DebugToolbar::class,
'honeypot' => Honeypot::class,
'cors' => \App\Filters\CorsFilter::class, //register cors
];
Kita register dengan nama cors didalam variable $alias.
Kita install terlebih dahulu package JWT dengan command seperti berikut.
composer require firebase/php-jwt
Kemudian kita buat sebuah library baru bernama JWTCI4, dan masukkan kode berikut.
<?php
namespace App\Libraries;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
class JWTCI4 {
private $key;
private $iss;
private $ttl; //in minutes
private $iat;
private $exp;
private $nbf;
private $jti;
public function __construct()
{
$this->setConfig()->setExpiredDate();
}
protected function setConfig()
{
$this->key = getenv("jwt.secretkey");
$this->ttl = getenv("jwt.ttl") ? getenv("jwt.ttl") : 60;
$this->iss = $this->getCurrentURL();
$this->jti = $this->setTime( date("Y-m-d H:i:s"));
return $this;
}
protected function setExpiredDate()
{
$now = date("Y-m-d H:i:s");
$this->iat = $this->setTime( $now );
$this->nbf = $this->setTime( $now );
$this->exp = $this->setTime( date("Y-m-d H:i:s", strtotime("+".$this->ttl." MINUTES")) );
return $this;
}
public function token()
{
$payload = [
'iss' => $this->iss,
'iat' => $this->iat,
'exp' => $this->exp,
'nbf' => $this->nbf,
'jti' => $this->jti
];
return JWT::encode($payload, $this->key, 'HS256');
}
public function parse($token)
{
$bearerToken = $this->getBearerToken( $token );
if( !$bearerToken ) return ['success' => false, 'message' => 'Token Invalid'];
try {
$decoded = JWT::decode($bearerToken, new Key($this->key, 'HS256') );
return ['success' => true];
}catch (\Exception $e){
return ['success' => false, 'message' => $e->getMessage()];
}
}
public function getBearerToken($token)
{
$token = explode(" ", $token);
if( !isset($token[0]) && $token[0] != 'Bearer' )
{
return false;
}
return $token[2];
}
public function setTime($date)
{
return strtotime($date);
}
public function getCurrentURL()
{
$url = ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https://' : 'http://') . $_SERVER['HTTP_HOST']. $_SERVER['REQUEST_URI'];
return $url;
}
}
Kita buka kembali file .env dan tambahkan beberapa variable berikut.
#JWT
jwt.secretkey= 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTY1MTAyOTU5MSwiaWF0IjoxNjUxMDI5NTkxfQ.GEqEGG2K-AQwjGEwDRzChXRIQVm5GtJPbTfcXHrgX5w'
jwt.ttl = 1440
Ada dua varibale yaitu secret key dan ttl. Secret key nantinya akan digunakan sebgai key saat generate token JWT, sedangkan ttl digunakan untuk setting expired date token tersebut. Untuk format time nya kita pakai menit. Contoh diatas yang kita pakai adalah 1440 menit atau 24 jam.
Selanjutnya kita buat midleware untuk authentifikasi bahwa API harus diakses menggunakan token JWT. Caranya kita buat sebuah file Filter bernama AuthFilter.php, dan masukkan kode seperti berikut.
use App\Libraries\JWTCI4;
...
/**
* @param RequestInterface $request
* @param array|null $arguments
*
* @return mixed
*/
public function before(RequestInterface $request, $arguments = null)
{
if( !$request->getHeader('Authorization') )
{
$response = service('response');
$response->setJSON(['success' => false, 'message' => 'Unauthorized. Token is required!']);
$response->setStatusCode(401);
return $response;
}
//validasi JWT
$token = $request->getHeader('Authorization');
$jwt = new JWTCI4;
$verifiy = $jwt->parse($token);
if( !$verifiy['success'] )
{
$response = service('response');
$response->setJSON($verifiy);
$response->setStatusCode(401);
return $response;
}
}
...
Jangan lupa untuk di register terlebih dahulu.
/**
* Configures aliases for Filter classes to
* make reading things nicer and simpler.
*
* @var array
*/
public $aliases = [
'csrf' => CSRF::class,
'toolbar' => DebugToolbar::class,
'honeypot' => Honeypot::class,
'cors' => \App\Filters\CorsFilter::class,
'auth' => \App\Filters\AuthFilter::class, //register auth
];
Fungsi filter tersebut adalah untuk security agar tidak semua bisa mengakses API tersebut secara bebas.
Tambahkan beberapa route baru di file App\Config\Routes.php seperti berikut .
/*
* --------------------------------------------------------------------
* Route Definitions
* --------------------------------------------------------------------
*/
// We get a performance increase by specifying the default
// route since we don't have to scan directories.
$routes->group('api', ["filter" => "cors", "auth"], function($routes) {
$routes->get('users', 'Api\UserController::index');
$routes->post('users', 'Api\UserController::create');
$routes->get('users/(:num)', 'Api\UserController::show/$1');
$routes->patch('users/(:num)', 'Api\UserController::update/$1');
$routes->delete('users/(:num)', 'Api\UserController::delete/$1');
});
$routes->post('api/users/token', 'Api\AuthController::login', ['filter' => 'cors']);
Berikut hasil REST API kita test menggunakan Postman.
Demikan tutorial kali ini. Semoga bermanfaat.
Untuk full sourcode bisa kalian lihat diaccount github sobatcoding di link berikut https://github.com/sobatcoding21/CI4RestApi.git.
Komentar 0