Di Part 8 kita sudah bisa register, login, dan mendapatkan access token. Tapi sampai sekarang token itu belum benar-benar dipakai untuk apapun — endpoint CRUD Post masih bisa diakses siapa saja tanpa token. Di part ini kita buat middleware yang memvalidasi JWT dan memproteksi endpoint yang sifatnya mengubah data.
Membuat Middleware
Buat file middleware/auth.go:
package middleware
import (
"strings"
"github.com/gofiber/fiber/v2"
"blogfiber/auth"
)
func AuthRequired(c *fiber.Ctx) error {
header := c.Get("Authorization")
if header == "" {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"message": "token tidak ditemukan",
})
}
parts := strings.SplitN(header, " ", 2)
if len(parts) != 2 || !strings.EqualFold(parts[0], "Bearer") {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"message": "format token tidak valid, gunakan: Bearer <token>",
})
}
claims, err := auth.ParseAccessToken(parts[1])
if err != nil {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"message": "token tidak valid atau sudah kadaluarsa",
})
}
c.Locals("user_id", claims.UserID)
return c.Next()
}
Alur middleware ini:
- Ambil header
Authorizationdari request. - Pastikan formatnya
Bearer <token>. - Verifikasi token pakai
auth.ParseAccessToken(yang sudah kita buat di Part 8) — kalau signature tidak cocok atau token sudah expired, ditolak dengan401. - Kalau valid, simpan
user_iddari klaim token kec.Locals("user_id", ...)supaya bisa diakses oleh handler berikutnya. - Panggil
c.Next()untuk melanjutkan ke handler tujuan.
Di Fiber, sebuah handler yang memanggil c.Next() (atau tidak memanggilnya sama sekali untuk menghentikan request) berperan sebagai middleware — tidak ada tipe khusus, cukup fungsi dengan signature func(*fiber.Ctx) error seperti handler biasa.
Menerapkan Middleware ke Route
Middleware bisa didaftarkan langsung sebagai argumen tambahan sebelum handler pada route tertentu. Update routes/routes.go:
posts := api.Group("/posts")
posts.Get("/", postHandler.Index)
posts.Get("/:id", postHandler.Show)
posts.Post("/", middleware.AuthRequired, postHandler.Create)
posts.Put("/:id", middleware.AuthRequired, postHandler.Update)
posts.Delete("/:id", middleware.AuthRequired, postHandler.Delete)
Kita sengaja hanya memproteksi Create, Update, dan Delete — endpoint Index dan Show tetap publik supaya siapa saja bisa membaca daftar/detail post tanpa perlu login, mirip pola read-public/write-protected yang umum dipakai di API blog.
Testing
Coba akses endpoint yang diproteksi tanpa token:
curl -i -X POST http://127.0.0.1:3000/api/v1/posts \
-H "Content-Type: application/json" \
-d '{"title":"Test","slug":"test","body":"body"}'
Akan dibalas 401 Unauthorized dengan pesan token tidak ditemukan.
Login dulu untuk dapat token, lalu sertakan di header Authorization:
TOKEN=$(curl -s -X POST http://127.0.0.1:3000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"budi@example.com","password":"rahasia123"}' | jq -r .access_token)
curl -X POST http://127.0.0.1:3000/api/v1/posts \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"title":"Test With Token","slug":"test-with-token","body":"body"}'
Kali ini request berhasil dan post tersimpan. Coba juga kirim token yang salah/rusak — middleware akan menolak dengan 401 token tidak valid atau sudah kadaluarsa. Sementara endpoint GET /api/v1/posts tetap bisa diakses tanpa token sama sekali.
Endpoint CRUD kita sekarang sudah punya proteksi dasar. Tapi access token kita berumur pendek (15 menit) — di part berikutnya kita akan tambahkan refresh token supaya user tidak perlu login ulang setiap 15 menit, plus endpoint logout.
Bagian dari Series: GoFiber Dasar - Belajar Fundamental Lewat REST API Blog
Belajar konsep-konsep dasar GoFiber (routing, handler, GORM, MySQL, JWT auth) dengan membangun REST API blog sederhana dari nol - lengkap dengan auten...
Lihat Series Lengkap