REST API Security Best Practices: Panduan Lengkap Melindungi Endpoint dari Serangan
REST API kini menjadi tulang punggung hampir setiap aplikasi modern, mulai dari mobile app, single-page application, hingga integrasi antar microservice. Sayangnya, popularitas ini juga menjadikannya target utama para penyerang. Berbeda dengan aplikasi web tradisional yang punya session dan CSRF token otomatis, REST API sering kali terekspos langsung ke internet tanpa lapisan pelindung tambahan. Artikel ini membahas praktik terbaik keamanan REST API, mulai dari cara kerja celah, demonstrasi eksploitasi, hingga langkah mitigasi yang bisa langsung Anda terapkan.
Ancaman Utama pada REST API
OWASP API Security Top 10 mencatat beberapa risiko yang paling sering ditemukan di lapangan. Yang paling berbahaya adalah Broken Object Level Authorization (BOLA) alias IDOR, di mana API hanya memeriksa apakah user sudah login, tetapi tidak memverifikasi apakah user tersebut berhak mengakses objek yang diminta. Selain itu ada Broken Authentication, Injection, Mass Assignment, Excessive Data Exposure, dan penyalahgunaan rate limiting.
Kesalahan paling umum adalah menganggap autentikasi sebagai satu-satunya lapisan keamanan. Padahal, autentikasi hanya menjawab pertanyaan "siapa Anda", sementara authorization menjawab "apa yang boleh Anda lakukan". Keduanya wajib diterapkan secara terpisah.
Contoh Implementasi: Autentikasi JWT dan Otorisasi Objek
Berikut middleware Express.js yang melakukan verifikasi token JWT sekaligus memeriksa kepemilikan resource sebelum data dikembalikan.
const jwt = require('jsonwebtoken');
// Middleware autentikasi
function authenticate(req, res, next) {
const authHeader = req.headers['authorization'];
if (!authHeader) return res.status(401).json({ error: 'Token tidak ada' });
const token = authHeader.split(' ')[1]; // Format: "Bearer <token>"
try {
// Wajib menyertakan algoritma agar tidak bisa di-bypass ke "none"
const payload = jwt.verify(token, process.env.JWT_SECRET, {
algorithms: ['HS256'],
});
req.user = payload;
next();
} catch (err) {
return res.status(403).json({ error: 'Token tidak valid' });
}
}
// Route dengan otorisasi level objek (mencegah BOLA/IDOR)
app.get('/api/invoices/:id', authenticate, async (req, res) => {
const invoice = await db.getInvoiceById(req.params.id);
if (!invoice) return res.status(404).json({ error: 'Not found' });
// PENTING: pastikan invoice milik user yang login
if (invoice.userId !== req.user.sub) {
return res.status(403).json({ error: 'Akses ditolak' });
}
res.json({ id: invoice.id, total: invoice.total });
});
Perhatikan bagian invoice.userId !== req.user.sub. Inilah pembeda antara API yang aman dan yang rentan. Tanpa baris tersebut, siapa pun yang sudah login bisa membaca tagihan milik pengguna lain hanya dengan mengganti nilai :id.
Analisis Keamanan: Bagaimana IDOR Dieksploitasi
Misalkan endpoint GET /api/invoices/1001 mengembalikan data milik Andi. Penyerang yang login sebagai user biasa cukup mengirim request dengan iterasi ID:
# Penyerang mengganti ID secara berurutan
curl -H "Authorization: Bearer <token-penyerang>" \
https://api.example.com/api/invoices/1002
Karena ID bersifat sequential dan mudah ditebak, penyerang dapat melakukan enumeration dengan script sederhana dan mengunduh seluruh database tagihan. Dampaknya adalah kebocoran data massal (data breach) yang bisa berujung pada sanksi regulasi seperti UU PDP atau GDPR.
Masalah serupa muncul pada SQL Injection jika query dibangun dengan string concatenation. Contoh query rentan: "SELECT * FROM users WHERE email = '" + email + "'". Penyerang cukup mengirim ' OR '1'='1 pada field email untuk melewati autentikasi sepenuhnya, atau memakai UNION SELECT untuk mencuri hash password.
Cara Pencegahan: Checklist Praktis
1. Terapkan otorisasi di setiap endpoint. Jangan pernah mengandalkan ID tersembunyi sebagai pengaman. Selalu validasi kepemilikan resource di sisi server.
2. Gunakan prepared statement / parameterized query. Hindari string concatenation sama sekali. Gunakan ORM atau query builder dengan parameter binding.
// SALAH
db.query(`SELECT * FROM users WHERE email = '${email}'`);
// BENAR
db.query('SELECT * FROM users WHERE email = ?', [email]);
3. Terapkan rate limiting dan throttling. Batasi jumlah request per IP atau per token untuk mencegah brute force dan enumeration, misalnya dengan library express-rate-limit.
4. Gunakan HTTPS dan HSTS. Token JWT yang dikirim via HTTP polos bisa disadap melalui serangan man-in-the-middle.
5. Terapkan Mass Assignment Protection. Jangan lakukan Object.assign(user, req.body) secara membabi buta, karena penyerang bisa menyisipkan field seperti role: "admin". Gunakan whitelist field yang boleh diubah.
6. Batasi data yang dikembalikan. Terapkan response filtering agar field sensitif seperti password_hash, internal_notes, atau reset_token tidak ikut terkirim.
7. Validasi dan sanitasi semua input. Gunakan skema validasi seperti Joi atau Zod untuk memastikan tipe data, panjang, dan format sesuai ekspektasi.
Kesimpulan
Keamanan REST API bukan fitur yang bisa ditambahkan belakangan, melainkan bagian inti dari arsitektur. Tiga pilar utama yang wajib Anda pegang adalah: autentikasi yang kuat, otorisasi level objek di setiap endpoint, dan validasi input dengan parameterized query. Celah seperti BOLA dan SQL Injection terjadi bukan karena teknologinya lemah, tetapi karena developer lupa memverifikasi hak akses di sisi server. Mulailah dari checklist di atas, terapkan secara konsisten, dan lakukan pengujian penetrasi secara berkala. Dengan begitu, API Anda tidak hanya berfungsi dengan baik, tetapi juga layak dipercaya untuk melindungi data pengguna.