pemrograman

10 Membuat Middleware Authentication Menggunakan Jwt

Dalam pengembangan aplikasi modern, autentikasi adalah salah satu komponen paling penting. JSON Web Tokens (JWT) adalah metode populer untuk menangani autentikasi berbasis token. Pada artikel ini, kita akan membuat middleware autentikasi menggunakan JWT di Golang dengan library httprouter dari julienschmidt.

Artikel ini dirancang untuk programmer pemula dengan langkah-langkah terperinci dan disertai penjelasan sehingga mudah diikuti.

Prasyarat

  1. Pemahaman dasar tentang Golang: Sebaiknya Anda sudah memahami dasar-dasar Golang seperti fungsi, struktur, dan modul.
  2. Golang terinstal: Pastikan Anda sudah menginstal Go di sistem Anda.
  3. Library pendukung: Kita akan menggunakan beberapa library tambahan, yaitu:
    • github.com/golang-jwt/jwt/v4 untuk mengelola JWT.
    • github.com/julienschmidt/httprouter untuk routing.

Untuk menginstal library di atas, gunakan perintah:

go get github.com/golang-jwt/jwt/v4 github.com/julienschmidt/httprouter

Langkah 1: Membuat Struktur Proyek

Buat struktur folder berikut:

project-root/
├── main.go
├── middleware/
│   └── auth.go
├── handlers/
│   └── user.go
├── utils/
│   └── jwt.go

File main.go adalah entry point aplikasi, sedangkan folder lainnya mengelompokkan berbagai fungsi dan middleware.


Langkah 2: Membuat Main File

Buka file main.go dan tuliskan kode berikut:

package main

import (
	"fmt"
	"log"
	"net/http"
	"github.com/julienschmidt/httprouter"
	"project-root/middleware"
	"project-root/handlers"
)

func main() {
	router := httprouter.New()

	// Endpoint public tanpa autentikasi
	router.GET("/public", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		fmt.Fprint(w, "Endpoint publik tidak memerlukan autentikasi!\n")
	})

	// Endpoint private menggunakan middleware autentikasi
	router.GET("/private", middleware.JWTAuth(handlers.PrivateHandler))

	log.Println("Server berjalan di http://localhost:8080")
	log.Fatal(http.ListenAndServe(":8080", router))
}

Kode di atas adalah contoh minimal aplikasi yang menggunakan middleware untuk endpoint privat.


Langkah 3: Membuat Middleware JWT

Buka file middleware/auth.go dan tambahkan kode berikut:

package middleware

import (
	"net/http"
	"strings"
	"github.com/golang-jwt/jwt/v4"
	"project-root/utils"
	"github.com/julienschmidt/httprouter"
)

func JWTAuth(next httprouter.Handle) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
		tokenString := extractToken(r)
		if tokenString == "" {
			http.Error(w, "Authorization header missing", http.StatusUnauthorized)
			return
		}

		// Memvalidasi token
		claims, err := utils.ValidateJWT(tokenString)
		if err != nil {
			http.Error(w, "Token tidak valid", http.StatusUnauthorized)
			return
		}

		// Menambahkan data ke context (opsional)
		r = r.WithContext(context.WithValue(r.Context(), "user", claims))

		// Melanjutkan ke handler berikutnya
		next(w, r, ps)
	}
}

func extractToken(r *http.Request) string {
	bearer := r.Header.Get("Authorization")
	if bearer == "" || !strings.HasPrefix(bearer, "Bearer ") {
		return ""
	}
	return strings.TrimPrefix(bearer, "Bearer ")
}

Middleware ini mengekstrak token dari header Authorization, memvalidasi tokennya, dan melanjutkan ke handler berikutnya jika token valid.


Langkah 4: Membuat Handler untuk Endpoint Privat

Buka file handlers/user.go dan tambahkan kode berikut:

package handlers

import (
	"fmt"
	"net/http"
	"github.com/julienschmidt/httprouter"
)

func PrivateHandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	fmt.Fprint(w, "Selamat datang di endpoint privat! Token Anda valid.\n")
}

Handler ini hanya dapat diakses jika middleware JWT berhasil memvalidasi tokennya.


Langkah 5: Membuat Utilitas untuk JWT

Buka file utils/jwt.go dan tambahkan kode berikut:

package utils

import (
	"errors"
	"time"
	"github.com/golang-jwt/jwt/v4"
)

var secretKey = []byte("rahasia_super")

type CustomClaims struct {
	Username string `json:"username"`
	jwt.RegisteredClaims
}

func GenerateJWT(username string) (string, error) {
	claims := CustomClaims{
		Username: username,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(1 * time.Hour)),
		},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString(secretKey)
}

func ValidateJWT(tokenString string) (*CustomClaims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
		return secretKey, nil
	})
	if err != nil {
		return nil, err
	}

	claims, ok := token.Claims.(*CustomClaims)
	if !ok || !token.Valid {
		return nil, errors.New("token tidak valid")
	}

	return claims, nil
}

File ini berisi fungsi untuk membuat dan memvalidasi JWT. GenerateJWT digunakan untuk membuat token, sedangkan ValidateJWT untuk memeriksa keabsahan token.


Langkah 6: Menguji Aplikasi

Jalankan aplikasi dengan perintah berikut:

go run main.go

Cobalah endpoint berikut menggunakan alat seperti curl atau Postman.

1. Endpoint Public (Tanpa Token)

curl http://localhost:8080/public

Respons:

Endpoint publik tidak memerlukan autentikasi!

2. Endpoint Private (Dengan Token)

Pertama, buat token menggunakan GenerateJWT (implementasikan di aplikasi lain atau secara manual untuk tes awal). Lalu, gunakan token untuk mengakses endpoint privat:

curl -H "Authorization: Bearer <TOKEN_ANDA>" http://localhost:8080/private

Jika token valid, responsnya adalah:

Selamat datang di endpoint privat! Token Anda valid.

Kesimpulan

Anda telah berhasil membuat middleware autentikasi menggunakan JWT di Golang dengan httprouter. Dengan pendekatan ini, Anda dapat memastikan bahwa endpoint-endpoint sensitif hanya dapat diakses oleh pengguna yang telah terautentikasi. Middleware ini juga fleksibel untuk diterapkan di aplikasi produksi.

Semoga artikel ini membantu Anda memahami konsep dasar JWT di Golang. Jika ada pertanyaan, jangan ragu untuk bertanya atau eksplorasi lebih lanjut!

comments powered by Disqus