CSRF Protection — Auth

CSRF (Cross-Site Request Forgery) memanfaatkan session yang sudah login untuk mengeksekusi aksi tanpa sepengetahuan user. Contoh: user login ke bank.com, lalu m

CSRF (Cross-Site Request Forgery) memanfaatkan session yang sudah login untuk mengeksekusi aksi tanpa sepengetahuan user. Contoh: user login ke bank.com, lalu mengunjungi evil.com yang diam-diam mengirim POST bank.com/transfer menggunakan cookie session yang masih aktif.

Kenapa ini bisa terjadi? Browser otomatis mengirim cookie untuk domain tujuan, termasuk dari request cross-site. Tanpa proteksi, server menerima request tersebut sebagai permintaan sah.

Tiga lapis pertahanan:

1. SameSite Cookie (proteksi dasar, nilai default modern):

Set-Cookie: session=abc; HttpOnly; Secure; SameSite=Lax

2. CSRF Token (Synchronizer Token Pattern):

// Server mengeluarkan token per session dan menyimpannya
const csrfToken = crypto.randomBytes(32).toString("hex");
session.csrfToken = csrfToken;

// Form harus menyertakan token ini
// <input type="hidden" name="_csrf" value="${csrfToken}">

// Server memvalidasi saat mutation (POST/PUT/DELETE)
if (request.body._csrf !== session.csrfToken) {
  return res.status(403).json({ error: "Invalid CSRF token" });
}

Token berbeda per session. Karena penyerang tidak bisa membaca cookie/session dari origin lain (Same-Origin Policy), mereka tidak bisa menebak token yang valid.

3. Double Submit Cookie (stateless alternative):

// Server mengirim token sebagai cookie DAN mengharapkan token yang sama di header
res.cookie("csrf-token", token, { sameSite: "strict" });

// Client membaca cookie dan mengirim ulang di header
fetch("/api/transfer", {
  headers: { "X-CSRF-Token": readCookie("csrf-token") }
});

// Server membandingkan kedua nilai
if (req.cookies["csrf-token"] !== req.headers["x-csrf-token"]) {
  return res.status(403).end();
}

Origin / Referer validation (safety net):

const trustedOrigins = ["https://myapp.com"];
if (!trustedOrigins.includes(req.headers.origin)) {
  return res.status(403).end();
}

Kapan tidak perlu CSRF token?

Kesalahan umum: