Skip to content
Santekno.com | Level Up Your Engineering Skills
ID
📖 0%
04 Feb 2025 · 5 mnt baca ·Artikel 75 / 119
Go

16 Membuat Middleware Hmac Authentication Pada Golang

IH
Ihsan Arif
Penulis di Santekno · Backend Engineer

Pada artikel kali ini, kita akan membahas bagaimana membangun middleware HMAC (Hash-based Message Authentication Code) Authentication menggunakan Go dan library httprouter. Middleware ini berfungsi untuk mengautentikasi permintaan HTTP berdasarkan tanda tangan HMAC, yang digunakan untuk memastikan integritas data yang dikirim dan bahwa data tersebut berasal dari sumber yang sah.

Apa Itu HMAC?

HMAC adalah sebuah metode untuk memberikan autentikasi dan integritas pada pesan atau data yang dikirim melalui jaringan. Dalam konteks API, HMAC digunakan untuk memverifikasi bahwa data yang diterima oleh server belum dimodifikasi dalam perjalanan dan bahwa data tersebut benar-benar dikirim oleh pengirim yang sah.

HMAC bekerja dengan menggunakan algoritma hash (misalnya SHA-256) yang digabungkan dengan sebuah kunci rahasia. Proses ini menghasilkan sebuah tanda tangan yang dapat diverifikasi oleh penerima. Jika tanda tangan cocok, maka data dianggap valid.

Persiapan Proyek

Untuk memulai, pastikan Anda sudah memiliki lingkungan pengembangan Go yang siap. Anda juga perlu menginstal httprouter dengan perintah:

bash
1go get github.com/julienschmidt/httprouter

Setelah itu, buat folder proyek baru dan buat file main.go di dalam folder tersebut.

Langkah 1: Menyiapkan Middleware HMAC

Middleware bertanggung jawab untuk memeriksa setiap permintaan yang datang, memverifikasi tanda tangan HMAC, dan memastikan bahwa permintaan tersebut berasal dari sumber yang sah. Berikut adalah kode dasar untuk middleware HMAC:

go
 1package main
 2
 3import (
 4	"crypto/hmac"
 5	"crypto/sha256"
 6	"encoding/hex"
 7	"fmt"
 8	"io/ioutil"
 9	"net/http"
10	"strings"
11
12	"github.com/julienschmidt/httprouter"
13)
14
15// Secret key untuk verifikasi HMAC
16var secretKey = []byte("your-secret-key")
17
18// Middleware HMAC
19func HMACMiddleware(next httprouter.Handle) httprouter.Handle {
20	return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
21		// Ambil tanda tangan dari header "X-Signature"
22		signature := r.Header.Get("X-Signature")
23		if signature == "" {
24			http.Error(w, "Missing signature", http.StatusUnauthorized)
25			return
26		}
27
28		// Ambil body request untuk membuat tanda tangan
29		body, err := ioutil.ReadAll(r.Body)
30		if err != nil {
31			http.Error(w, "Unable to read body", http.StatusInternalServerError)
32			return
33		}
34
35		// Buat HMAC dari body menggunakan kunci rahasia
36		mac := hmac.New(sha256.New, secretKey)
37		mac.Write(body)
38		expectedSignature := hex.EncodeToString(mac.Sum(nil))
39
40		// Verifikasi apakah tanda tangan sesuai
41		if !hmac.Equal([]byte(signature), []byte(expectedSignature)) {
42			http.Error(w, "Invalid signature", http.StatusUnauthorized)
43			return
44		}
45
46		// Lanjutkan ke handler berikutnya
47		next(w, r, ps)
48	}
49}

Penjelasan kode:

  1. Middleware HMACMiddleware memeriksa header X-Signature yang berisi tanda tangan HMAC dari pengirim.
  2. Kemudian, body dari permintaan dibaca untuk membangun HMAC dengan menggunakan kunci rahasia.
  3. HMAC yang dibangun dibandingkan dengan tanda tangan yang diterima di header untuk memverifikasi integritas dan autentikasi data.

Langkah 2: Menyiapkan Router dan Handler

Selanjutnya, kita perlu menyiapkan router httprouter dan handler untuk menangani permintaan yang berhasil diverifikasi tanda tangannya:

go
 1// Handler untuk halaman private yang membutuhkan otentikasi hmac
 2func ProtectedHMACHandler(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
 3	w.Write([]byte("Welcome to the session private page"))
 4}
 5
 6func main() {
 7	router := httprouter.New()
 8
 9	// sample for initiate hmac
10	mac := hmac.New(sha256.New, middleware.SecretKey)
11	mac.Write([]byte(`Hello World`))
12	validSignature := hex.EncodeToString(mac.Sum(nil))
13	fmt.Println("generate hmac sample: " + validSignature)
14
15	// Menggunakan middleware HMAC untuk endpoint ini
16	router.GET("/protected-hmac", middleware.HMAC(ProtectedHMACHandler))
17
18	// Menjalankan server
19	http.ListenAndServe(":8080", router)
20}

Dalam contoh ini, kita menambahkan route /hello yang dilindungi oleh middleware HMAC. Hanya permintaan yang memiliki tanda tangan yang valid yang akan dapat mengaksesnya.

Langkah 3: Pengujian HMAC dengan Unit Test

Untuk memastikan bahwa middleware HMAC berfungsi dengan baik, kita akan menulis unit test. Kita akan menguji dua kasus:

  1. Permintaan yang sah dengan tanda tangan yang valid.
  2. Permintaan dengan tanda tangan yang tidak valid.

Berikut adalah kode untuk unit test:

go
 1package main
 2
 3import (
 4	"net/http"
 5	"net/http/httptest"
 6	"testing"
 7	"time"
 8
 9	"github.com/julienschmidt/httprouter"
10	"github.com/stretchr/testify/assert"
11)
12
13func makeRequest(signature string, body string) *http.Request {
14	req := httptest.NewRequest(http.MethodGet, "/hello", strings.NewReader(body))
15	req.Header.Set("X-Signature", signature)
16	return req
17}
18
19func generateSignature(body string) string {
20	mac := hmac.New(sha256.New, SecretKey)
21	mac.Write([]byte(body))
22	return hex.EncodeToString(mac.Sum(nil))
23}
24
25func TestHMACMiddleware(t *testing.T) {
26	router := httprouter.New()
27	router.GET("/hello", HMAC(mockHMACHandler))
28
29	type args struct {
30		signature string
31		body      string
32	}
33	tests := []struct {
34		name             string
35		args             args
36		wantStatusCode   int
37		wantBodyContains string
38	}{
39		{
40			name: "valid HMAC signature",
41			args: args{
42				signature: generateSignature("Hello World"),
43				body:      "Hello World",
44			},
45			wantStatusCode:   http.StatusOK,
46			wantBodyContains: "Welcome to the session private page",
47		},
48		{
49			name: "invalid HMAC signature",
50			args: args{
51				signature: "invalid-signature",
52				body:      "Hello World",
53			},
54			wantStatusCode:   http.StatusUnauthorized,
55			wantBodyContains: "Invalid signature",
56		},
57		{
58			name: "signature is empty",
59			args: args{
60				signature: "",
61				body:      "Hello World",
62			},
63			wantStatusCode:   http.StatusUnauthorized,
64			wantBodyContains: "Missing signature",
65		},
66		{
67			name: "body was changed (error mismatch signature)",
68			args: args{
69				signature: generateSignature("Original Body"),
70				body:      "Tampered Body",
71			},
72			wantStatusCode:   http.StatusUnauthorized,
73			wantBodyContains: "Invalid signature",
74		},
75	}
76
77	for _, tt := range tests {
78		t.Run(tt.name, func(t *testing.T) {
79			req := makeRequest(tt.args.signature, tt.args.body)
80			rr := httptest.NewRecorder()
81
82			router.ServeHTTP(rr, req)
83
84			if rr.Code != tt.wantStatusCode {
85				t.Errorf("handler returned wrong status code: got %v, want %v", rr.Code, tt.wantStatusCode)
86			}
87			if !strings.Contains(rr.Body.String(), tt.wantBodyContains) {
88				t.Errorf("handler returned unexpected body: got %v, want to contain %v", rr.Body.String(), tt.wantBodyContains)
89			}
90		})
91	}
92}
93
94func mockHMACHandler(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
95	w.Write([]byte("Welcome to the session private page"))
96}

Penjelasan unit test:

  1. Test case 1: Kami membuat permintaan dengan tanda tangan yang valid dan memverifikasi bahwa responsnya adalah status 200 OK.
  2. Test case 2: Kami membuat permintaan dengan tanda tangan yang tidak valid dan memverifikasi bahwa server merespons dengan status 401 Unauthorized.

Untuk menjalankan unit test, gunakan perintah:

bash
1go test -v

Kesimpulan

Pada artikel ini, kita telah mempelajari bagaimana cara membangun middleware HMAC Authentication menggunakan Go dan httprouter. Middleware ini berguna untuk memastikan integritas dan autentikasi data yang dikirim melalui HTTP. Kita juga telah melihat bagaimana menulis unit test untuk memastikan middleware bekerja dengan baik.

Untuk lebih lanjut tentang Golang, Anda dapat mengunjungi Tutorial Golang . Jika Anda tertarik untuk mempelajari lebih lanjut tentang HTTP router di Go, silakan baca artikel mengenai Web HTTP Router pada Golang .

Dengan memahami konsep HMAC dan penerapannya dalam middleware, Anda bisa membangun sistem yang lebih aman dan dapat diandalkan. Semoga artikel ini bermanfaat dan mudah dipahami!

Artikel Terkait

💬 Komentar