Membuat refresh token di Gofiber
Langkah-langkah Implementasi Refresh Token
Update Helper JWT untuk Mendukung Refresh Token:
Tambahkan fungsi
GenerateRefreshToken
untuk menghasilkan refresh token dengan klaim yang sama namun waktu kedaluwarsa yang lebih lama.
// src/helpers/jwt.go package helpers import ( "time" "github.com/dgrijalva/jwt-go" ) // GenerateToken generates a JWT token with dynamic claims func GenerateToken(secretKey string, payload map[string]interface{}) (string, error) { token := jwt.New(jwt.SigningMethodHS256) claims := token.Claims.(jwt.MapClaims) for key, value := range payload { claims[key] = value } claims["exp"] = time.Now().Add(time.Hour * 1).Unix() tokenString, err := token.SignedString([]byte(secretKey)) if err != nil { return "", err } return tokenString, nil } // GenerateRefreshToken generates a refresh JWT token with dynamic claims func GenerateRefreshToken(secretKey string, payload map[string]interface{}) (string, error) { token := jwt.New(jwt.SigningMethodHS256) claims := token.Claims.(jwt.MapClaims) for key, value := range payload { claims[key] = value } claims["exp"] = time.Now().Add(time.Hour * 24).Unix() refreshTokenString, err := token.SignedString([]byte(secretKey)) if err != nil { return "", err } return refreshTokenString, nil }
Update Controller untuk Login dan Refresh Token:
Update fungsi
LoginUser
untuk mengembalikan access token dan refresh token.Tambahkan fungsi
RefreshToken
untuk menghasilkan token baru berdasarkan refresh token yang valid.
// 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) models.PostUser(&user) return c.Status(fiber.StatusCreated).JSON(fiber.Map{ "message": "Register successfully", }) } func LoginUser(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", }) } validateEmail := models.FindEmail(&user) if len(validateEmail) == 0 { return c.Status(fiber.StatusNotFound).JSON(fiber.Map{ "message": "Email not found", }) } var PasswordSecond string for _, user := range validateEmail { PasswordSecond = user.Password } if err := bcrypt.CompareHashAndPassword([]byte(PasswordSecond), []byte(user.Password)); err != nil || user.Password == "" { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ "message": "Invalid password", }) } jwtKey := os.Getenv("SECRETKEY") payload := map[string]interface{}{ "email": user.Email, } token, err := helpers.GenerateToken(jwtKey, payload) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "error": "Could not generate access token", }) } refreshToken, err := helpers.GenerateRefreshToken(jwtKey, payload) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "error": "Could not generate refresh token", }) } item := map[string]string{ "Email": user.Email, "Token": token, "RefreshToken": refreshToken, } return c.Status(fiber.StatusCreated).JSON(fiber.Map{ "message": "Login successfully", "data": item, }) } func RefreshToken(c *fiber.Ctx) error { var input struct { RefreshToken string `json:"refreshToken"` } if err := c.BodyParser(&input); err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "error": "Failed to parse request body", }) } jwtKey := os.Getenv("SECRETKEY") token, err := helpers.GenerateToken(jwtKey, map[string]interface{}{"refreshToken": input.RefreshToken}) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "error": "Could not generate access token", }) } refreshToken, err := helpers.GenerateRefreshToken(jwtKey, map[string]interface{}{"refreshToken": input.RefreshToken}) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "error": "Could not generate refresh token", }) } item := map[string]string{ "Token": token, "RefreshToken": refreshToken, } return c.Status(fiber.StatusCreated).JSON(fiber.Map{ "message": "Refresh successfully", "data": item, }) }
Update Routes untuk Mendukung Refresh Token:
Tambahkan route baru untuk
refreshToken
di file routes.
// 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) app.Post("/refreshToken", controllers.RefreshToken) }
Dengan langkah-langkah ini, Anda telah berhasil mengimplementasikan fitur refresh token dalam aplikasi. Refresh token memungkinkan pengguna untuk mendapatkan token baru tanpa perlu login ulang ketika token akses mereka kedaluwarsa.
Last updated