Dalam pengembangan aplikasi web dan mobile modern, mengamankan endpoint API adalah hal yang sangat penting. Salah satu metode autentikasi paling populer dan efisien saat ini adalah menggunakan JSON Web Token (JWT). JWT menawarkan cara yang stateless untuk memverifikasi identitas pengguna, menjadikannya pilihan ideal untuk arsitektur microservices dan API RESTful.
Panduan ini akan membawa Anda memahami apa itu JWT, bagaimana cara kerjanya, kelebihan dan kekurangannya, serta langkah-langkah dasar untuk mengimplementasikannya dalam aplikasi Anda. Mari kita selami cara kerja JWT dan mengapa ia menjadi pilihan favorit para developer.
Apa Itu JSON Web Token (JWT)?
JWT adalah standar terbuka (RFC 7519) yang mendefinisikan cara aman untuk mentransmisikan informasi antara dua pihak sebagai objek JSON. Informasi ini dapat diverifikasi karena ditandatangani secara digital. JWT sering digunakan untuk autentikasi dan otorisasi.
Sebuah JWT memiliki tiga bagian, dipisahkan oleh titik (.
):
- Header: Berisi metadata tentang token, seperti tipe token (JWT) dan algoritma hashing yang digunakan untuk tanda tangan (misalnya, HS256, RS256). JSON
{ "alg": "HS256", "typ": "JWT" }
- Payload (Claims): Berisi klaim (informasi) tentang entitas (biasanya pengguna) dan metadata tambahan. Ada tiga jenis klaim:
- Registered Claims: Klaim standar yang direkomendasikan tapi tidak wajib (misalnya,
iss
(issuer),exp
(expiration time),sub
(subject),aud
(audience)). - Public Claims: Klaim khusus yang bisa Anda definisikan sendiri, tapi disarankan untuk mendaftarkannya secara publik atau menghindari konflik nama.
- Private Claims: Klaim kustom yang disepakati antara pengirim dan penerima, tidak standar.
{ "sub": "1234567890", "name": "John Doe", "admin": true, "iat": 1516239022 // Issued At }
- Registered Claims: Klaim standar yang direkomendasikan tapi tidak wajib (misalnya,
- Signature (Tanda Tangan): Dihasilkan dengan menggabungkan Encoded Header, Encoded Payload, dan sebuah secret key (kunci rahasia) menggunakan algoritma hashing yang ditentukan di Header.
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )
Ketiga bagian ini kemudian di-encode menggunakan Base64Url dan digabungkan dengan titik, menghasilkan string JWT yang kita kenal: xxxxx.yyyyy.zzzzz
Bagaimana Cara Kerja Autentikasi dengan JWT?
Siklus autentikasi dengan JWT biasanya melibatkan langkah-langkah berikut:
- Login Pengguna:
- Pengguna mengirimkan kredensial (misalnya, username dan password) ke server (API backend).
- Verifikasi Kredensial:
- Server memverifikasi kredensial pengguna terhadap database atau sistem autentikasi lainnya.
- Pembuatan JWT:
- Jika kredensial valid, server membuat JWT yang berisi payload (misalnya, ID pengguna, role, waktu kadaluarsa).
- JWT ini ditandatangani menggunakan secret key yang hanya diketahui oleh server.
- Pengiriman JWT ke Klien:
- Server mengirimkan JWT kembali ke klien (aplikasi frontend atau mobile). JWT ini biasanya disertakan dalam body respons atau sebagai header
Authorization
.
- Server mengirimkan JWT kembali ke klien (aplikasi frontend atau mobile). JWT ini biasanya disertakan dalam body respons atau sebagai header
- Penyimpanan JWT di Klien:
- Klien menyimpan JWT, biasanya di Local Storage, Session Storage, atau cookies (dengan pengaturan
HttpOnly
untuk keamanan tambahan).
- Klien menyimpan JWT, biasanya di Local Storage, Session Storage, atau cookies (dengan pengaturan
- Akses ke Sumber Daya Terlindungi (Authenticated Requests):
- Setiap kali klien ingin mengakses endpoint API yang dilindungi, klien menyertakan JWT dalam header
Authorization
sebagai Bearer Token.
Authorization: Bearer <your_jwt_token_here>
- Setiap kali klien ingin mengakses endpoint API yang dilindungi, klien menyertakan JWT dalam header
- Verifikasi JWT di Server:
- Ketika server menerima permintaan dengan JWT, ia akan:
- Mengekstrak JWT dari header
Authorization
. - Memverifikasi tanda tangan JWT menggunakan secret key yang sama.
- Memeriksa apakah token sudah kadaluarsa (
exp
claim). - Jika tanda tangan valid dan token belum kadaluarsa, server menganggap pengguna terautentikasi dan mengizinkan akses ke sumber daya. Informasi dari payload (misalnya, ID pengguna) dapat digunakan untuk otorisasi (menentukan apa yang boleh diakses pengguna).
- Mengekstrak JWT dari header
- Ketika server menerima permintaan dengan JWT, ia akan:
- Logout Pengguna:
- Ketika pengguna logout, klien cukup menghapus JWT dari penyimpanannya. Tidak ada pembatalan token di sisi server secara default (kecuali diimplementasikan secara manual dengan blacklist).
Kelebihan JWT
- Stateless: Server tidak perlu menyimpan informasi sesi. Setiap permintaan dari klien berisi semua yang dibutuhkan server untuk memverifikasi identitas. Ini sangat baik untuk skalabilitas karena permintaan dapat diarahkan ke server manapun tanpa khawatir tentang sticky sessions.
- Keamanan: Tanda tangan digital mencegah manipulasi token. Jika token diubah, server akan mendeteksinya.
- Portabilitas: JWT dapat digunakan di berbagai platform dan bahasa pemrograman.
- Compact: Ukurannya relatif kecil, cocok untuk transmisi melalui URL, POST parameter, atau HTTP header.
- Decentralized Authorization: Informasi otorisasi (misalnya, role pengguna) dapat disertakan dalam payload, memungkinkan microservices yang berbeda untuk memverifikasi otorisasi tanpa perlu menghubungi database pusat setiap kali.
Kekurangan JWT
- Tidak Ada Pembatalan Token (Revocation) Bawaan: Setelah JWT diterbitkan, server tidak memiliki kontrol langsung untuk membatalkannya sebelum waktu kadaluarsanya. Jika token dicuri, ia tetap valid sampai kadaluarsa. Solusinya memerlukan implementasi blacklist token di sisi server.
- Ukuran Payload: Meskipun compact, payload yang terlalu besar dapat meningkatkan ukuran header permintaan. Informasi sensitif tidak boleh disimpan di payload karena hanya di-encode, bukan dienkripsi.
- Keamanan Secret Key: Keamanan JWT sangat bergantung pada kerahasiaan secret key. Jika secret key bocor, penyerang dapat membuat JWT palsu.
- Refresh Token Complexity: Untuk mengatasi masalah revocation dan masa berlaku yang singkat, sering digunakan kombinasi access token (JWT berumur pendek) dan refresh token (token berumur panjang). Ini menambah kompleksitas implementasi.
Contoh Implementasi Sederhana (Konseptual dengan Node.js/Express.js)
Berikut adalah contoh konseptual bagaimana JWT dapat diimplementasikan menggunakan Node.js dengan Express.js.
1. Instalasi Library
Bash
npm install express jsonwebtoken dotenv
2. Konfigurasi (server.js)
JavaScript
// server.js
const express = require('express');
const jwt = require('jsonwebtoken');
const dotenv = require('dotenv');
dotenv.config(); // Load environment variables from .env file
const app = express();
app.use(express.json()); // For parsing application/json
const PORT = process.env.PORT || 3000;
const JWT_SECRET = process.env.JWT_SECRET || 'your_secret_key'; // Ganti dengan kunci rahasia yang kuat!
// Data pengguna dummy (simulasi database)
const users = [
{ id: 1, username: 'user1', password: 'password1', role: 'user' },
{ id: 2, username: 'admin', password: 'adminpassword', role: 'admin' }
];
// Middleware untuk memverifikasi JWT
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN_ANDA
if (token == null) return res.sendStatus(401); // Tidak ada token
jwt.verify(token, JWT_SECRET, (err, user) => {
if (err) return res.sendStatus(403); // Token tidak valid atau kadaluarsa
req.user = user; // Menambahkan informasi pengguna dari payload ke objek request
next(); // Lanjutkan ke route berikutnya
});
}
// --- Routes ---
// Route Login
app.post('/login', (req, res) => {
const { username, password } = req.body;
const user = users.find(u => u.username === username && u.password === password);
if (user) {
// Buat JWT
const accessToken = jwt.sign(
{ id: user.id, username: user.username, role: user.role },
JWT_SECRET,
{ expiresIn: '1h' } // Token akan kadaluarsa dalam 1 jam
);
res.json({ accessToken: accessToken });
} else {
res.status(401).json({ message: 'Invalid credentials' });
}
});
// Route yang dilindungi (hanya bisa diakses dengan JWT valid)
app.get('/protected', authenticateToken, (req, res) => {
res.json({ message: `Halo, ${req.user.username}! Anda berhasil mengakses resource yang dilindungi.` });
});
// Route yang dilindungi dan membutuhkan role admin
app.get('/admin-only', authenticateToken, (req, res) => {
if (req.user.role !== 'admin') {
return res.status(403).json({ message: 'Akses ditolak. Perlu hak akses admin.' });
}
res.json({ message: `Selamat datang, Admin ${req.user.username}!` });
});
app.listen(PORT, () => {
console.log(`Server berjalan di http://localhost:${PORT}`);
});
3. File .env (untuk Kunci Rahasia)
Buat file .env
di root proyek Anda:
JWT_SECRET=SUPER_RAHASIA_DAN_PANJANG_DAN_ACAK
Penting: Ganti SUPER_RAHASIA_DAN_PANJANG_DAN_ACAK
dengan string yang sangat panjang, acak, dan sulit ditebak. Gunakan tool generator untuk ini. Jangan pernah ekspos kunci ini ke publik!
Peran Refresh Token
Untuk mengatasi kekurangan JWT terkait pembatalan dan masa berlaku singkat, sering digunakan Refresh Token:
- Access Token (JWT): Berumur pendek (misalnya, 15 menit - 1 jam). Digunakan untuk mengakses resource API yang dilindungi. Jika dicuri, hanya valid untuk waktu singkat.
- Refresh Token: Berumur panjang (misalnya, 7 hari - 30 hari). Disimpan di database server dan digunakan hanya untuk meminta access token baru ketika access token lama kadaluarsa.
- Alur:
- Pengguna login, server memberikan Access Token dan Refresh Token.
- Klien menggunakan Access Token untuk permintaan API.
- Ketika Access Token kadaluarsa, klien mengirimkan Refresh Token ke server.
- Server memverifikasi Refresh Token terhadap database. Jika valid, server mengeluarkan Access Token baru dan mungkin juga Refresh Token baru.
- Jika Refresh Token dicurigai atau dibatalkan, server tidak akan mengeluarkan Access Token baru, memaksa pengguna untuk login ulang.
Efektif dan Scalable
JWT adalah solusi yang efektif dan scalable untuk autentikasi dan otorisasi dalam aplikasi modern. Kemampuannya untuk menyediakan informasi stateless dan dapat diverifikasi membuatnya menjadi pilihan yang sangat baik untuk API RESTful dan arsitektur microservices.
Meskipun memiliki kelebihan dalam skalabilitas dan keamanan integritas data, penting untuk memahami kekurangannya, terutama terkait pembatalan token. Dengan implementasi yang tepat, termasuk pengelolaan secret key yang aman dan pertimbangan penggunaan refresh token, Anda dapat membangun sistem autentikasi yang kuat dan andal menggunakan JWT.
0 Komentar
Artikel Terkait
