Basic backend dengan Gofiber part 2 Membuat middleware menggunahkan JWT(JSON Web Token) di Gofiber Konsep JWT (JSON Web Token)
JWT adalah metode yang digunakan untuk mengamankan komunikasi antara client dan server dengan cara membuat token yang berisi klaim-klaim tertentu, seperti user ID atau email. Token ini kemudian dikirim bersama setiap permintaan untuk memverifikasi identitas pengguna.
Install Package JWT : Jalankan perintah berikut untuk menginstall paket jwt-go
:
Copy go get github.com/dgrijalva/jwt-go
Setup Environment Variables : Tambahkan variabel lingkungan untuk menyimpan kunci rahasia JWT. Buat file .env
dan tambahkan:
Copy SECRETKEY=your_secret_key_here
Helper JWT : Buat helper untuk menghasilkan token JWT.
Copy // src/helpers/jwt.go
package helpers
import (
"time"
"github.com/dgrijalva/jwt-go"
)
func GenerateToken(secretKey, email string) (string, error) {
token := jwt.New(jwt.SigningMethodHS256)
claims := token.Claims.(jwt.MapClaims)
claims["email"] = email
claims["exp"] = time.Now().Add(time.Hour * 1).Unix()
return token.SignedString([]byte(secretKey))
}
Middleware JWT : Buat middleware untuk memeriksa validitas token JWT.
Copy // src/middlewares/jwt.go
package middlewares
import (
"fmt"
"os"
"strings"
"github.com/dgrijalva/jwt-go"
"github.com/gofiber/fiber/v2"
)
func ExtractToken(c *fiber.Ctx) string {
bearerToken := c.Get("Authorization")
if strings.HasPrefix(bearerToken, "Bearer ") {
return strings.TrimPrefix(bearerToken, "Bearer ")
}
return ""
}
func JwtMiddleware() fiber.Handler {
secretKey := os.Getenv("SECRETKEY")
return func(c *fiber.Ctx) error {
tokenString := ExtractToken(c)
if tokenString == "" {
return c.Status(fiber.StatusUnauthorized)
.JSON(fiber.Map{"error": "Unauthorized"})
}
_, err := jwt.Parse(tokenString, func(token *jwt.Token)
(interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v",
token.Header["alg"])
}
return []byte(secretKey), nil
})
if err != nil {
return c.Status(fiber.StatusUnauthorized)
.JSON(fiber.Map{"error": "Unauthorized"})
}
return c.Next()
}
}
Model User : Buat model untuk user.
Copy // src/models/Users.go
package models
import (
"gofiber/src/configs"
"gorm.io/gorm"
)
type User struct {
gorm.Model
Email string `json:"email"`
Password string `json:"password"`
}
func PostUser(user *User) error {
return configs.DB.Create(user).Error
}
func FindEmail(email string) (*User, error) {
var user User
result := configs.DB.Where("email = ?", email).First(&user)
return &user, result.Error
}
Controller User : Buat controller untuk registrasi dan login user.
Copy // src/controllers/UserController.go
package controllers
import (
"gofiber/src/helpers"
"gofiber/src/models"
"os"
"github.com/gofiber/fiber/v2"
"golang.org/x/crypto/bcrypt"
)
func RegisterUser(c *fiber.Ctx) error {
var user models.User
if err := c.BodyParser(&user); err != nil {
return c.Status(fiber.StatusBadRequest)
.JSON(fiber.Map{"error": "Failed to parse request body"})
}
hashPassword, _ := bcrypt.GenerateFromPassword([]byte(user.Password),
bcrypt.DefaultCost)
user.Password = string(hashPassword)
if err := models.PostUser(&user); err != nil {
return c.Status(fiber.StatusInternalServerError)
.JSON(fiber.Map{"error": "Failed to create user"})
}
return c.Status(fiber.StatusCreated)
.JSON(fiber.Map{"message": "Register successfully"})
}
func LoginUser(c *fiber.Ctx) error {
var input models.User
if err := c.BodyParser(&input); err != nil {
return c.Status(fiber.StatusBadRequest)
.JSON(fiber.Map{"error": "Failed to parse request body"})
}
user, err := models.FindEmail(input.Email)
if err != nil {
return c.Status(fiber.StatusNotFound)
.JSON(fiber.Map{"message": "Email not found"})
}
if err := bcrypt.CompareHashAndPassword([]byte(user.Password),
[]byte(input.Password)); err != nil {
return c.Status(fiber.StatusUnauthorized)
.JSON(fiber.Map{"message": "Invalid password"})
}
token, err := helpers.GenerateToken(os.Getenv("SECRETKEY"), user.Email)
if err != nil {
return c.Status(fiber.StatusInternalServerError)
.JSON(fiber.Map{"error": "Failed to generate token"})
}
return c.JSON(fiber.Map{"message": "Login successfully", "token": token})
}
Router : Tambahkan rute untuk registrasi dan login user.
Copy // src/routes/main.go
package routes
import (
"gofiber/src/controllers"
"gofiber/src/middlewares"
"github.com/gofiber/fiber/v2"
)
func Router(app *fiber.App) {
// Product routes
app.Get("/products", controllers.GetAllProducts)
app.Get("/product/:id", controllers.GetProductById)
app.Post("/product", controllers.CreateProduct)
app.Put("/product/:id", controllers.UpdateProduct)
app.Delete("/product/:id", controllers.DeleteProduct)
// Category routes
app.Get("/categories", middlewares.JwtMiddleware(),
controllers.GetAllCategories)
app.Get("/category/:id", controllers.GetCategoryById)
app.Post("/category", controllers.CreateCategory)
app.Put("/category/:id", controllers.UpdateCategory)
app.Delete("/category/:id", controllers.DeleteCategory)
// User routes
app.Post("/register", controllers.RegisterUser)
app.Post("/login", controllers.LoginUser)
}
Migrasi Database : Tambahkan migrasi untuk model User
.
Copy // src/helpers/migration.go
package helpers
import (
"gofiber/src/configs"
"gofiber/src/models"
)
func Migration() {
configs.DB.AutoMigrate(&models.Product{}, &models.Category{}, &models.User{})
}
Dengan mengikuti langkah-langkah di atas, Anda dapat mengimplementasikan keamanan JWT untuk autentikasi dan menambahkan header keamanan menggunakan Helmet untuk meningkatkan keamanan aplikasi Fiber Anda.