Assalamu'alaikum Wr. Wb.
Pada kesempatan kali ini saya ingin membagikan sebuah tutorial sekaligus salah satu pengalaman yaitu implementasi JWT (JSON Web Token) pada Framework Laravel, khususnya yang akan saya gunakan kali ini adalah Laravel 9. JSON Web Token atau jika disingkat JWT adalah salah satu model autentikasi untuk mengakses sebuah server menggunakan token, karakteristik utama pada token JWT adalah dapat menyimpan data JSON atau objek yang dienkripsi secara aman yang memerlukan kunci khusus (biasanya string) untuk mendecode data di dalam token. Langsung saja untuk implementasi JWT pada Laravel adalah sebagai berikut.
Instalasi JWT pada Laravel
- Install JWT
mengutip dari website resmi Laravel JWT Auth, untuk menginstall JWT anda perlu masuk ke root directory project Laravel anda dan jalankan perintah berikut:
composer require php-open-source-saver/jwt-auth - Mempublikasikan konfigurasi
Untuk mempublikasikan konfigurasi JWT pada Laravel anda, anda dapat menjalankan perintah berikut:
php artisan vendor:publish --provider="PHPOpenSourceSaver\JWTAuth\Providers\LaravelServiceProvider"
Setelah menjalankan perintah diatas anda akan mendapatkan file config/jwt.php untuk mengonfigurasikan JWT pada Project Laravel anda. - Menggenerate Secret Key
Langkah selanjutnya adalah menggenerate secret key, secret key adalah kunci yang digunakan untuk mendecode token JWT, untuk menggenerate secret key anda dapat menjalankan perintah berikut:
php artisan jwt:secret
Dengan perintah di atas anda akan mendapatkan sebuah property JWT_SECRET beserta value nya berupa string acak di file .env pada Project Laravel anda. Perintah di atas hanya digunakan untuk mempermudah anda menggenerate secret key, sebenarnya anda dapat membuat kunci JWT sendiri tanpa menggunakan perintah di atas jika anda mau. - Menggenerate Certificate (Opsional)
Certificate yang dimaksud di sini adalah pasangan private key dan public key, private key digunakan untuk menandatangani token dan public key digunakan untuk memvalidasi token tersebut saat token diterima kembali oleh server dari client, untuk menggenerate certificate yaitu pasangan public key dan private key anda dapat menjalan perintah berikut:
php artisan jwt:generate-certs
dengan perintah tersebut akan mengupdate file .env dengan pasangan property dan value diantaranya JWT_ALGO (jenis algoritma untuk menandatangani token), JWT_PRIVATE_KEY (lokasi private key), JWT_PUBLIC_KEY (lokasi public key), JWT_PASSPHRASE (kata sandi untuk mengenkripsi private key jika digunakan) yang mana nilai dari properti tersebut digunakan sebagai nilai untuk mengonfigurasi JWT di file jwt.php.
Dikatakan opsional karena sebagai pengaman tambahan, jika anda tidak menggunakan private dan public key sebagai pengaman tambahan maka token tidak ditandatangani private key sebagai pengaman tambahan, untuk informasi lengkapnya anda dapat membacanya disini. - Implementasi JWTSubject pada Model
Selanjutnya agar kita dapat mengimplementasikan token JWT pada api kita kita perlu menambahkan implements JWTSubject pada class model Auth atau User (model yang digunakan untuk autentikasi) dan menambahkan function getJWTIdentifier() dan function getJWTCustomClaims() hingga model User atau Auth anda akan terlihat sebagai berikut:
<?php
namespace App
use PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements JWTSubjects
{
use Notifiable;
// Rest omitted for brievity
/ **
* Get the identifier that will be stored in the subject claim of the JWT.
*
* @return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT
*
* @return array
*/
public function getJWTCustomClaims()
{
return [];
}
} - Mengonfigurasi Auth Guard
Langkah selanjutnya kita akan mengonfigurasi guard untuk api kita, pertama masuk ke file config/auth.php lalu ubah dan atau tambahkan kode berikut:
'default' => [
'guard' => 'api'
'password' => 'user'
]
....
'guards' => [
....
'api' => [
'driver' => 'jwt',
'provider' => 'users'
]
]
Auth guard digunakan untuk mengatur autentikasi pengguna yang ingin mengakses aplikasi server kita, jika dibandingakan dengan middleware ada sedikit perbedaan, walaupun sebenarnya middleware juga dapat digunakan untuk autentikasi pada pengertian umum fungsi middleware digunakan untuk memanipulasi request HTTP sebelum mencapai tujuan akhir, dan pada kasus autentikasi token JWT middleware yang diterapkan pada route (langkah ke 7) sebenarnya mengacu pada guard api. - Menambahkan middleware untuk validasi token JWT di Route
Selanjutnya agar token yang kita kirimkan ke server dapat divalidasi menggunakan driver jwt maka kita harus menambahkan middleware tersebut di route aplikasi kita, contoh kode setelah ditambahkan middleware untuk jwt adalah sebagai berikut:
Route::group(['prefix' => 'user'], function () {
Route::post('/login', [UserController::class, 'login']);
});
Route::middleware('auth:api')->group(function(){
Route::group(['prefix' => 'user'], function () {
Route::get('/', [UserController::class, 'get_users']);
});
});
Dengan kode di atas hanya route yang menggunakan middleware auth:api yang harus diautentikasi terlebih dahulu sebelum dilanjutkan ke controller. - Menerapkan JWT pada Controller
Setelah instalasi selesai kita sudah dapat menerapkan fungsi-fungsi dari package JWT yang sebelumnya kita pasang, contoh penggunaannya adalah sebagai berikut:
Ketika user melakukan login
Saat login kita perlu menambahkan function untuk mengautentikasi user dan menggenerate token untuk digunakan pada api-api lainnya, ada dua function bawaan package JWT yaitu:
$token = auth()->attempt($credentials);
$token = auth()->login($user);
Kedua fungsi tersebut dapat kita pilih salah satu untuk kita gunakan untuk menggenerate token ketika user melakukan login, perbedaan antara kedua function tersebut adalah:
Parameter: auth()->attempt($credentials) menerima array yang berisi informasi otentikasi (biasanya berupa email dan password), sedangkan auth()->login($user) menerima objek User.
Pengembalian: auth()->attempt($credentials) mengembalikan token jika informasi otentikasi valid dan null jika tidak valid, sedangkan auth()->login($user) selalu mengembalikan token baru tanpa mengecek informasi otentikasi.
Konteks: auth()->attempt($credentials) umumnya digunakan untuk otentikasi berbasis formulir, sedangkan auth()->login($user) digunakan ketika kita ingin secara manual membuat token untuk pengguna tertentu.
Ketika ingin mendapatkan refresh token;
Merefresh token adalah menggenerate token baru, hal ini berfungsi jika user ingin mendapatkan token dengan waktu expired yang baru agar user tetap dalam keadaan login jika user belum ingin melakukan logout, tapi perlu diingan user harus terautentikasi menggunakan parameter auth:api terlebih dahulu sebelum mendapatkan token terbaru, untuk kodenya adalah sebagai berikut:
$newToken = auth()->refresh(true, true);
Parameter pertama pada function di atas berfungsi untuk memaksa token lama untuk di blacklist, dan parameter kedua digunakan untuk mereset claims untuk token baru.
Ketika user melakukan logout
Untuk menonaktifkan token yang sebelumnya digunakan ketika user melakukan logout maka kita perlu menambahkan kode perikut saat kita melakukan logut:
$auth->logout(true);
Parameter true yang ditambahkan pada function di atas sebenarnya opsional, tetapi dengan parameter true diatas maka token user yang sudah tidak digunakan akan dipaksa di blacklist agar tidak bisa digunakan lagi. - Mengonfigurasi waktu expired token JWT
Kita dapat mengonfigurasi waktu expired atau kadaluarsa dari token kita dengan mengedit value dari property di dalam file config/jwt.php, misal sebagai berikut:
'ttl' => env('JWT_TTL', 60);
Dengan konfigurasi di atas berarti token akan expired dalam waktu 60 menit setelah token digenerate, bisa disimpulkan value 60 di atas berarti per satuan menit, misal jika anda ingin mengatur token agar memiliki waktu expired 1 hari(24 jam) anda tinggal mengalikannya saja 60 x 24 = 1440. - Menggunakan middleware custom untuk validasi token JWT
Selain menggunakan middleware auth:api kita bisa membuat middleware custom untuk memvalidasi token JWT kita, untuk membuat middleware baru anda dapat menggunakan perintah berikut pada terminal:
php artisan make:middleware NamaMiddleware
Setelah anda membuat middleware anda harus mendaftarkan middleware custom yang anda buat di file app/Http/kernel.php pada variable protected $routeMiddleware = [ ... ]; sebagai berikut:
protected $routeMiddleware = [
...
'jwt' => \App\Http\Middleware\JWT::class,
];
Setelah anda membuat dan mendaftarkan middleware anda perlu menambahkan kode berikut di middleware baru anda:
try {
JWTAuth::parseToken()->authenticate();
} catch (TokenExpiredException $e) {
return response()->json(['error' => 'Token is expired'], 401);
} catch (TokenBlacklistedException $e) {
return response()->json(['error' => 'Token no longer grant access to server'], 401);
} catch (TokenInvalidException $e) {
return response()->json(['error' => 'Token is invalid'], 401);
} catch (JWTException $e) {
return response()->json(['error' => 'Token is not attached'], 401);
}
return $next($request);
Keterangan dari kode di atas adalah sebagai berikut:
JWTAuth::parseToken()->authenticate(); = untuk mengautentikasi token JWT user
TokenExpiredException = menangkap error ketika token sudah kadaluarsa
TokenBlacklistedException = menangkap error ketika token sudah di blacklist
TokenInvalidException = menangkap error ketika token tidak valid
JWTException = digunakan untuk menangkap error lain (misal token tidak dilampirkan pada request)
Dengan menggunakan middleware custom tersebut maka kesalahan-kesalahan pada token JWT yang dikirim dari user ke server dapat ditangkap dan dikembalikan response kesalahan tersebut.
Jika anda menggunakan middleware custom sebagai autentikasi token JWT maka penerapan token JWT pada route perlu diubah sesuai nama middleware JWT yang sudah anda daftarkan pada app/Http/kernel.php, contoh kodenya adalah sebagai berikut:
Route::group(['prefix' => 'user'], function () {
Route::post('/login', [UserController::class, 'login']);
});
Route::middleware('jwt')->group(function(){
Route::group(['prefix' => 'user'], function () {
Route::get('/', [UserController::class, 'get_users']);
});
});
Sumber: https://laravel-jwt-auth.readthedocs.io/en/latest/
0 Komentar