Episode ini membahas autentikasi JWT di Fiber: middleware github.com/gofiber/contrib/jwt, signing key dengan HS256, akses claims di handler, penerbitan token saat login, serta middleware security untuk header keamanan respons.

Autentikasi API modern banyak bergantung pada JSON Web Token (JWT) — token yang bisa diverifikasi tanpa menyimpan state di server. Episode 16 membahas pemakaian JWT di Fiber v3: middleware dari github.com/gofiber/contrib/jwt, cara membaca claims, penerbitan token saat login, dan middleware security untuk header respons.
JWT memang praktis, tapi rawan salah pakai. Kunci signing yang bocor, algoritma yang lemah, dan token yang tidak kedaluwarsa adalah sumber masalah umum. Karena itu episode ini juga menekankan praktik keamanan di sekitarnya.
Package contrib/jwt membungkus golang-jwt/jwt/v5. Konfigurasi minimal: algoritma signing dan kunci:
import jwtware "github.com/gofiber/contrib/jwt"
app.Use("/protected", jwtware.New(jwtware.Config{
SigningKey: jwtware.SigningKey{
JWTAlg: jwtware.HS256,
Key: []byte("secret-rahasia-ubah-ini"),
},
ContextKey: "jwt",
Claims: jwt.MapClaims{},
}))SigningKey menentukan algoritma (HS256) dan kunci rahasia. Claims: jwt.MapClaims{} memberi tahu middleware struktur klaim yang diharapkan. Middleware ini dipasang pada prefix /protected sehingga setiap route di bawahnya menuntut token valid — request tanpa token atau token rusak langsung ditolak.
Pemilihan algoritma menentukan cara mengelola kunci:
// HS256: satu kunci rahasia untuk sign dan verify
Key: []byte(os.Getenv("JWT_SECRET"))
// RS256: private key untuk sign, public key untuk verify
// cocok untuk banyak service
JWTAlg: jwtware.RS256,
Key: rsaPublicKey,HS256 memakai satu kunci rahasia — cepat dan sederhana, cocok untuk satu service. RS256 memakai pasangan kunci: service lain cukup memegang public key untuk memverifikasi, tanpa tahu private key. Pilih RS256 saat token divalidasi lintas service.
Setelah lolos middleware, token tersimpan di context. Handler mengambilnya lewat c.Locals dengan ContextKey:
app.Get("/protected/profile", func(c fiber.Ctx) error {
token := c.Locals("jwt").(*jwt.Token)
claims := token.Claims.(jwt.MapClaims)
name := claims["name"].(string)
role := claims["role"].(string)
return c.JSON(fiber.Map{"name": name, "role": role})
})c.Locals("jwt").(*jwt.Token) mengambil token hasil verifikasi. Dari token.Claims (bertipe jwt.MapClaims) kalian membaca klaim seperti name dan role. Pola ini menjadi dasar otorisasi — misalnya menolak akses jika role != "admin".
Client mengirim token melalui header Authorization. Middleware contrib/jwt default memakai Authorization: Bearer <token>:
curl -H "Authorization: Bearer <TOKEN>" http://localhost:3000/protected/profileTanpa header, middleware membalas 401 Unauthorized. Dengan token valid, handler mengekstrak claims dan mengembalikan data pengguna.
Token harus dibuat di suatu tempat — biasanya endpoint login. Di sini kunci signing yang sama dipakai untuk menandatangani:
app.Post("/login", func(c fiber.Ctx) error {
var creds Credentials
if err := c.Bind().JSON(&creds); err != nil {
return err
}
user, err := verifyLogin(creds)
if err != nil {
return fiber.NewError(fiber.StatusUnauthorized, "kredensial salah")
}
claims := jwt.MapClaims{
"name": user.Name,
"role": user.Role,
"exp": time.Now().Add(time.Hour).Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
signed, err := token.SignedString([]byte(os.Getenv("JWT_SECRET")))
if err != nil {
return err
}
return c.JSON(fiber.Map{"token": signed})
})Login memverifikasi kredensial, menyusun claims (termasuk exp satu jam), menandatangani token, dan mengembalikannya. Klaim exp wajib ada agar token kedaluwarsa — jangan membuat token tanpa batas waktu.
Selain JWT, Fiber menyediakan middleware security untuk mengatur header keamanan respons:
app.Use(security.New(security.Config{
XSSProtection: "1; mode=block",
ContentTypeNosniff: "nosniff",
XFrameOptions: "SAMEORIGIN",
HSTSMaxAge: 3600,
HSTSExcludeSubdomains: false,
}))Middleware ini menambahkan header seperti X-XSS-Protection, X-Content-Type-Options, X-Frame-Options, dan Strict-Transport-Security. Header-nya disetel langsung pada c.Response().Header, melindungi respons dari serangan kelas XSS, clickjacking, dan MIME sniffing.
TOKEN=$(curl -s -X POST -H "Content-Type: application/json" \
--data '{"username":"budi","password":"rahasia123"}' \
http://localhost:3000/login | python3 -c "import sys,json;print(json.load(sys.stdin)['token'])")
curl -H "Authorization: Bearer $TOKEN" http://localhost:3000/protected/profilePertama ambil token dari /login, lalu pakai token itu di header Authorization. Tanpa token, /protected/profile membalas 401; dengan token valid, handler membaca claims name dan role.
Inti yang harus dibawa pulang:
github.com/gofiber/contrib/jwt dengan SigningKey (HS256/RS256).c.Locals(ContextKey) sebagai *jwt.Token; claims diakses dari token.Claims.Authorization: Bearer <token>.exp) dengan SignedString.security menambahkan header keamanan respons.Di episode 17 selanjutnya kita membahas file upload — multipart form dengan middleware multipart, konfigurasi Memory, akses FormFile, dan penyimpanan file yang aman.