Episode ini membahas keamanan web di Fiber v3: middleware csrf dengan KeyLookup dan konfigurasi cookie, middleware cors dengan AllowOrigins dan kredensial, serta kombinasi praktik untuk melindungi API dari serangan lintas situs.

Web memiliki ancaman yang melekat pada cara kerjanya: situs lain bisa memanfaatkan browser pengguna untuk mengirim request yang tidak diinginkan. Episode 18 membahas dua middleware yang melindungi dari ancaman ini — CSRF dan CORS — serta cara mengkombinasikannya.
CSRF mencegah situs jahat memaksa browser mengirim request berbahaya ke aplikasi kalian; CORS mengontrol situs mana yang diizinkan membaca respons. Keduanya wajib dipahami saat membangun API yang dipakai browser.
csrf.New() melindungi mutasi state (POST, PUT, DELETE) dengan token per sesi:
app.Use(csrf.New())Tanpa konfigurasi, middleware membuat token CSRF, menyimpannya di cookie, dan memvalidasi request berikutnya. Jika request mengandung token yang cocok, diteruskan; jika tidak, dikembalikan error. Token dibuat secara acak per pengunjung dan harus dikirim ulang di setiap mutasi.
Secara default token dibaca dari header X-CSRF-Token. Ubah sumber token dengan KeyLookup:
app.Use(csrf.New(csrf.Config{
KeyLookup: "header:X-CSRF-Token",
ErrorHandler: func(c fiber.Ctx, err error) error {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{
"error": "token CSRF tidak valid",
})
},
}))KeyLookup: "header:X-CSRF-Token" berarti token diharapkan ada di header tersebut. Format source:key juga mendukung cookie:csrf atau form:csrf. ErrorHandler mengubah respons default menjadi JSON — penting agar konsisten dengan API.
Cookie yang menyimpan token juga perlu diatur agar aman:
app.Use(csrf.New(csrf.Config{
CookieName: "csrf_token",
CookieHTTPOnly: true,
CookieSameSite: "Lax",
}))CookieHTTPOnly: true mencegah JavaScript membaca token lewat document.cookie — mengurangi risiko pencurian. CookieSameSite: "Lax" memblokir pengiriman cookie pada request lintas situs, menutup vektor CSRF utama. CookieSecure sebaiknya diaktifkan di produksi agar cookie hanya dikirim lewat HTTPS.
CORS mengontrol situs mana yang boleh membaca respons:
app.Use(cors.New())Dengan default, semua origin diizinkan (AllowOrigins: "*"). Ini tidak aman untuk API yang menyimpan data sensitif — setiap situs bisa membaca respons. Untuk API publik tanpa autentikasi cookie, default ini kadang diterima; untuk API lain, batasi origin secara eksplisit.
Untuk produksi, daftarkan origin yang diizinkan secara eksplisit:
app.Use(cors.New(cors.Config{
AllowOrigins: "https://gofiber.io, https://gofiber.net",
AllowHeaders: "Origin, Content-Type, Accept, Authorization",
AllowMethods: "GET, POST, PUT, DELETE, OPTIONS",
}))AllowOrigins menerima daftar origin yang dipisahkan koma; selain itu dibalas tanpa header CORS. AllowHeaders dan AllowMethods mengumumkan apa yang boleh dikirim. Jika client memakai cookie dengan CORS, tambahkan AllowCredentials: true — dan ingat, AllowCredentials tidak boleh dipakai bersama origin wildcard *.
Untuk daftar origin yang dinamis — misalnya dari database — pakai AllowOriginsFunc:
app.Use(cors.New(cors.Config{
AllowOriginsFunc: func(origin string) bool {
return strings.HasSuffix(origin, ".myapp.example.com")
},
}))AllowOriginsFunc mengembalikan true untuk setiap origin yang cocok. Contoh ini mengizinkan semua subdomain .myapp.example.com tanpa mendaftarkannya satu per satu — berguna saat tenant membuat subdomain baru secara dinamis.
Urutan pemasangan middleware menentukan perilaku. Konvensi yang disarankan:
app.Use(recover.New())
app.Use(cors.New(cors.Config{AllowOrigins: "https://app.example.com"}))
app.Use(csrf.New())
api := app.Group("/api", jwtware.New(jwtware.Config{
SigningKey: jwtware.SigningKey{Key: []byte(secret)},
}))recover diletakkan paling luar agar panic tidak membunuh server; cors mengatur header untuk semua respons; csrf melindungi mutasi; dan JWT menjaga area /api. CSRF biasanya tidak diperlukan untuk API yang murni token-based — pilih sesuai kebutuhan: cookie-based session memakai CSRF, token-based memakai JWT.
curl -i http://localhost:3000/
curl -i -H "Origin: https://evil.example.com" http://localhost:3000/api/dataRequest pertama menampilkan header CSRF di respons. Request kedua dari origin asing tidak menerima header Access-Control-Allow-Origin — browser akan memblokir pembacaan respons. Coba dengan origin yang terdaftar dan bandingkan hasilnya.
Inti yang harus dibawa pulang:
csrf.New() melindungi mutasi dengan token per sesi; default token di header X-CSRF-Token.KeyLookup mengatur sumber token: header:, cookie:, atau form:.CookieHTTPOnly, CookieSameSite, dan CookieSecure.cors.New() default mengizinkan semua origin — batasi dengan AllowOrigins untuk produksi.AllowCredentials: true tidak boleh digabung dengan origin wildcard.AllowOriginsFunc cocok untuk daftar origin dinamis.Di episode 19 selanjutnya kita membahas sessions dan autentikasi — middleware session dengan penyimpanan Redis/Memcache/MySQL, penyimpanan data session, serta alur autentikasi lengkap.