Menjawab Tantangan Hardening Auth Nuxt

Untuk memperkuat autentikasi API dan middleware Nuxt 3, fokus utama adalah memastikan sesi dikunci dengan cookie HttpOnly/Secure, validasi token yang bersih, rotasi secret yang bisa diandalkan pada SSR/serverless, serta mekanisme rate limit untuk mencegah abuse. Pendekatan ini menjawab kebutuhan langsung penguatan lapisan auth tanpa mengubah arsitektur secara drastis.

Dalam artikel ini akan dibahas pengaturan session cookie, implementasi guard middleware, praktik rotasi secret, dan batas permintaan yang dapat diterapkan tim Nuxt untuk membuat stack autentikasi lebih tahan terhadap serangan sesi, eksposur credential, dan lonjakan permintaan.

Menjaga Session Cookie HttpOnly dan Secure

Cookie sesi adalah titik lemah umum jika tidak diberi atribut pengamanan. Di Nuxt 3, buat middleware server atau nitroHook untuk menyetel cookie dengan atribut httpOnly, secure, dan sameSite=Lax agar skrip klien tidak bisa mengaksesnya.

Contoh pengaturan di server/api/session.post.ts untuk memberikan cookie setelah login:

import { serialize } from 'cookie';
export default defineEventHandler(async (event) => {
  const sessionId = await createSessionForUser();
  const cookie = serialize('session_id', sessionId, {
    httpOnly: true,
    secure: event.node.req.headers['x-forwarded-proto'] === 'https',
    sameSite: 'lax',
    path: '/',
    maxAge: 60 * 60
  });
  setHeader(event, 'Set-Cookie', cookie);
  return { status: 'ok' };
});

Dengan backend SSR, pastikan semua respons API yang menginisiasi sesi juga mematuhi header Set-Cookie yang konsisten. Untuk log out, kirim header cookie dengan maxAge=0. Periksa apakah deployment Anda berada di domain yang statis; jika tidak, gunakan konfigurasi domain secara eksplisit di serialize.

Validasi Token dan Guard Middleware

Nilai autentikasi kepercayaan bergantung pada middleware yang memverifikasi token di setiap permintaan. Dalam Nuxt, buat middleware server serta guard SSR yang mengecek cookie session atau header Bearer.

Contoh guard di server/middleware/auth.ts:

export default defineEventHandler(async (event) => {
  const authHeader = getRequestHeader(event, 'authorization');
  const sessionCookie = parseCookies(event)?.['session_id'];
  const token = sessionCookie ?? authHeader?.replace('Bearer ', '');
  if (!token || !(await verifyToken(token))) {
    throw createError({ statusCode: 401, statusMessage: 'Unauthorized' });
  }
  event.context.user = await fetchUserFromToken(token);
});

Pasang middleware ini di router API dan gunakan defineNuxtRouteMiddleware di halaman yang membutuhkan autentikasi. Pastikan verifyToken memvalidasi signature, expiry, dan tidak hanya format JWT.

Untuk SSR, gunakan guard yang sama melalui useNuxtApp().$fetch atau server/api untuk memastikan data awal (data fetching) terlindungi. Jangan mengandalkan hanya middleware klien karena user transition ke route baru harus divalidasi di server juga.

Rotasi Secret untuk Serverless dan SSR

Rotasi secret menjaga JWT signing key, cookie encryption key, dan API secret tidak tertinggal saat breach terdeteksi atau tim berkembang. Di lingkungan Nuxt 3 Serverless (Nitro), jangan menaruh secret pada file .env yang tidak terenkripsi. Gunakan secret manager seperti AWS Parameter Store, Azure Key Vault, atau GitHub Secrets.

Prinsip rotasi sederhana:

  • Simak dua versi secret: AUTH_SECRET_CURRENT dan AUTH_SECRET_PREVIOUS untuk memberikan window rotasi.
  • Nitro dapat membaca keduanya dari env. Saat memverifikasi token, coba validasi dengan secret saat ini dulu, lalu secret sebelumnya sebelum gagal.
  • Deploy proses background untuk membuat secret baru, menyinkronkan dengan client release, lalu setelah beberapa waktu matikan secret lama.

Contoh verifikasi rotasi di helper:

const secrets = [process.env.AUTH_SECRET_CURRENT, process.env.AUTH_SECRET_PREVIOUS].filter(Boolean);
export function verifyToken(token: string) {
  for (const secret of secrets) {
    try {
      return jwtVerify(token, secret);
    } catch (error) {
      if (error.name !== 'JsonWebTokenError') continue;
    }
  }
  throw new Error('Invalid token');
}

Perhatikan trade-off: menambahkan secret sebelumnya memungkinkan gradien rollout, tetapi memperpanjang waktu validitas token lama dan berpotensi mengekspos sesi jika secret lama bocor. Pastikan secret lama dilepas setelah semua pengguna upgrade.

Batas Permintaan dan Abuse Prevention

Rate limit melindungi endpoint auth dari brute force. Untuk Nuxt API yang berjalan di Nitro, gunakan middleware rate limit berbasis Redis untuk menjaga state lintas instance. Berikut pendekatan sederhana:

import { redis } from '@/lib/redis';
export default defineEventHandler(async (event) => {
  const key = `rl:${getRequestHeader(event, 'x-real-ip')}`;
  const count = await redis.incr(key);
  if (count === 1) {
    await redis.expire(key, 60);
  }
  if (count > 30) {
    throw createError({ statusCode: 429, statusMessage: 'Too Many Requests' });
  }
});

Jika Redis tidak tersedia, gunakan cache memori internal dengan TTL, tapi pahami bahwa cache hanya efektif per instance Nitro. Untuk API publik, pertimbangkan menyertakan header Retry-After pada respons 429 dan log setiap pemblokiran untuk analisis.

Tambah lapisan abuse prevention dengan captchas atau email verification di titik login/registrasi yang sensitif. Saat rate limit diterapkan, siapkan metrics untuk mendeteksi false positive karena forward proxy atau VPN yang berbagi IP.

Audit Secret dan Lingkungan

Audit adalah langkah terakhir untuk memastikan konfigurasi auth tetap aman. Prioritaskan:

  1. Scan repo untuk kompromi secret (misalnya git-secrets).
  2. Gunakan tooling CI/CD untuk memvalidasi bahwa .env tidak berisi nilai produksi selain pada secret manager.
  3. Set up automated rotation schedules dan catat tanggal rotasi terakhir di dokumentasi internal.
  4. Verifikasi permintaan runtime bahwa Nuxt membaca secret yang benar dengan meniki log Nitro dan memeriksa process.env saat proses start.

Jika menggunakan serverless, audit deployment pipeline untuk memastikan secret hanya di-inject saat runtime. Jangan menaruh secret dalam build artifact Nuxt, karena build statis bisa dicuri dari CDN.

Terakhir, dokumentasikan proses emergency rotation: siapa yang memicu, bagaimana meng-update client, serta cara mengirimkan notifikasi jika sesi perlu dihapus.

Kesiapan Operasional

Setelah menerapkan semua lapisan di atas, pastikan ada observabilitas. Pantau error 401/429 di log aggregator, gunakan alert ketika threshold rate limit terlampaui, dan lakukan testing integrasi untuk sesi login di lingkungan staging.

Dengan pendekatan pragmatis tersebut, tim Nuxt dapat meningkatkan keamanan autentikasi tanpa membangun ulang arsitektur, sekaligus memudahkan troubleshooting dan rotasi secret.