Strategi keamanan API Route Next.js yang efektif menggabungkan otentikasi yang kuat, kontrol laju akses, serta pengawasan operasional. Dalam dua paragraf ini, pembaca langsung mendapatkan gambaran solusi: middleware menjaga validitas token/sesi, rate limit menetapkan batas adaptif, dan observabilitas mendeteksi kegagalan autentikasi atau pelanggaran rate limit.
Alur Otentikasi Token dan Validasi Sesi
Persyaratan utama API aman adalah memastikan hanya klien terautentikasi yang bisa mencapai logic bisnis. Selama permintaan API Route, prosesnya sebaiknya seperti berikut: (1) middleware atau handler membaca header Authorization atau cookie sesi, (2) token diverifikasi signature-nya (JWT, HMAC, atau opaque token), (3) payload diperiksa klaim seperti exp dan scope, serta (4) jika perlu, validasi terhadap store session/token di backend untuk mendeteksi revocation.
Di Next.js, struktur middleware memberi titik masuk sebelum API route dieksekusi. Contoh berikut menunjukkan pemeriksaan token Bearer dengan rotasi secret sederhana:
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
const allowedSecrets = [process.env.API_SECRET_PRIMARY, process.env.API_SECRET_SECONDARY];
export function middleware(req: NextRequest) {
const authHeader = req.headers.get('authorization');
if (!authHeader) return NextResponse.json({ error: 'Missing Authorization' }, { status: 401 });
const token = authHeader.replace('Bearer ', '');
const isValid = allowedSecrets.some(secret => verifyToken(token, secret));
if (!isValid) return NextResponse.json({ error: 'Invalid token' }, { status: 401 });
req.nextUrl.searchParams.set('user', extractUserId(token));
return NextResponse.next();
}
function verifyToken(token: string, secret?: string) {
if (!secret) return false;
// Verifikasi JWT atau HMAC sesuai implementasi
return token === secret; // placeholder logika
}
Perhatikan bahwa rotasi secret bisa dilakukan dengan menjaga array allowedSecrets yang menyertakan secret aktif dan cadangan. Saat secret baru diterbitkan, tambahkan ke array sebelum menghapus yang lama; ini menjaga permintaan klien yang masih menggunakan secret lama bisa disetujui sementara.
Pembandingan Stateful vs Stateless
Pendekatan stateless (misal JWT) menyimpan klaim di token sehingga server tidak perlu penyimpanan tambahan. Namun, stateless sulit dihentikan jika kompromi token tanpa mekanisme revocation, sehingga beberapa tim menggabungkan pengecekan terhadap store (Redis, database) untuk mencatat token yang dibatalkan. Pendekatan stateful menyimpan session ID di server dan cocok jika tim ingin memudahkan invalidasi sesi real-time, namun perlu skalabilitas store yang cepat.
Untuk keseimbangan, kombinasikan JWT dengan store kecil (allowlist atau blacklist) dan verifikasi periode. Contoh: sebelum memproses API, cek apakah token ada di cache revocation. Jika tidak, lanjutkan; jika ada, tolak.
Rate Limit Adaptif dan Mitigasi Abuse
Setelah otentikasi valid, langkah berikutnya ialah menghindari penyalahgunaan API dengan kontrol laju. Rate limit adaptif merujuk pada limit per klien yang bisa bervariasi berdasarkan typenya (misalnya token layanan internal vs pengguna publik). Implementasinya mengandalkan store cepat (Redis, Memory) yang menyimpan hit counter per key.
Contoh pendekatan Next.js API Route (handler) dengan Redis rate limit:
import type { NextApiRequest, NextApiResponse } from 'next';
import { createClient } from 'redis';
const redis = createClient({ url: process.env.REDIS_URL });
redis.connect();
const LIMIT = 100;
const WINDOW = 60; // detik
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const key = `rate:${req.headers['x-api-key'] || req.headers.authorization}`;
const current = await redis.incr(key);
if (current === 1) await redis.expire(key, WINDOW);
if (current > LIMIT) {
console.error('RATE_LIMIT_EXCEEDED', { key, current });
return res.status(429).json({ error: 'Rate limit exceeded' });
}
// Proses permintaan normal
res.status(200).json({ success: true, remaining: LIMIT - current });
}
Optimalkan rate limit adaptif dengan menyimpan metadata tentang jenis token. Misalnya API key layanan internal boleh 500 request per menit, sementara pengguna biasa 60. Gunakan switch berdasarkan klaim token atau header untuk menetapkan nilai LIMIT dan WINDOW.
Jangan lupa untuk menangani permintaan file upload besar atau eksekusi skrip otomatis. Misalnya, apabila API menerima multipart upload, lengkapi middleware untuk memvalidasi ukuran Content-Length dan deny jika melebihi threshold, lalu masukkan metadata ke rate limit sehingga upload berat juga dihitung dalam quota.
Penanganan Secret dan Metadata
Secret seperti API key, JWT signing key, atau database credential harus dikelola lewat environment variable dan metadata di platform (Vercel, AWS Parameter Store). Pastikan rilisan pipeline tidak mencetak secret ke log; gunakan sistem yang memisah konfigurasi dan kode.
Rotasi secret harus dilakukan dengan tahapan berikut: (1) buat credential baru dan tambahkan ke array valid, (2) distribusikan ke runtime (via deployments), (3) tunggu periode grace, (4) hapus credential lama. Catat waktu rotasi di observabilitas sehingga tim bisa menyelidiki error otentikasi pasca-rotasi.
Observabilitas dan Logging Keamanan
Menolak request karena otentikasi atau rate limit harus tercatat dengan detail untuk mempermudah debugging. Idealnya log mencakup ID request, sumber (IP/API key), alasan penolakan, dan timestamp. Contoh logging di handler seperti:
if (!isValid) {
console.warn('AUTH_FAILURE', { path: req.url, sourceIp: req.headers['x-forwarded-for'], reason: 'invalid token' });
return res.status(401).json({ error: 'Unauthorized' });
}
Tambahkan metrik ke observability platform (Prometheus, Grafana) untuk melacak jumlah penolakan otentikasi, kejadian rate limit, dan latensi API. Data ini membantu melihat tren abuse atau konfigurasi limit yang terlalu ketat.
Kolaborasi Frontend/Backend
Tim frontend perlu memahami format token/API key, mekanisme refresh, dan apa yang harus dilakukan saat menerima response 401/429. Dokumentasikan endpoint refresh dan error handling di API contract. Tim backend wajib menyediakan header seperti Retry-After pada 429 agar klien tahu kapan mencoba lagi.
Praktik terbaik: buat helper consistent di frontend untuk menyisipkan Authorization header, memeriksa response, dan men-trigger proses refresh. Backend selanjutnya melakukan validasi di middleware tanpa mengandaikan klien tertentu.
Ringkasan dan Checklist Implementasi
- Pasang middleware Next.js untuk memverifikasi token, memeriksa session/state jika diperlukan, dan menyuntikkan metadata pengguna ke
req. - Terapkan rate limit adaptif berbasis tipe token dengan store seperti Redis, serta log event limit untuk diagnosa.
- Kelola secret melalui environment variable/metadata, sertakan mekanisme rotasi dengan grace period.
- Catat failure otentikasi dan rate limit secara struktural untuk observabilitas (misal JSON log dengan field reason, key, status).
- Koordinasi dengan tim frontend agar penanganan response 401/429 konsisten dan klien mengirim header yang dibutuhkan.
Dengan pendekatan end-to-end ini, API Route Next.js akan lebih tahan terhadap abuse, mudah diawasi, dan siap untuk kolaborasi tim lintas frontend-backend.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!