Skip to content
Santekno.com | Level Up Your Engineering Skills
ID
📖 0%
30 Oct 2025 · 6 mnt baca ·Artikel 122 / 125
Go

122 Studi Kasus: Sistem Registrasi & Login JWT dengan gqlgen

IH
Ihsan Arif
Penulis di Santekno · Backend Engineer

122 Studi Kasus: Sistem Registrasi & Login JWT dengan gqlgen

Membangun sistem autentikasi yang aman dan efisien adalah salah satu pondasi hampir seluruh aplikasi backend modern. Di era API-first development dan microservices, JSON Web Token (JWT) menjadi salah satu solusi authentication yang paling populer. Di kasus kali ini, saya akan membagikan studi kasus membangun sistem registrasi & login menggunakan JWT dengan GraphQL di Go, memanfaatkan library powerful gqlgen .

Kita akan membahas arsitektur, contoh kode, hingga flow diagram alur request – lengkap dengan simulasi login dan proteksi endpoint.


Gambaran Umum Sistem

Sistem yang akan kita buat mencakup fitur berikut:

  1. Registrasi User
  2. Login User
  3. Proteksi Endpoint dengan JWT

Komponen utama yang digunakan:

  • Go sebagai backend language
  • gqlgen sebagai GraphQL code generator
  • gorilla/mux (opsional) sebagai HTTP router
  • JWT (github.com/golang-jwt/jwt/v5) untuk pembuatan dan validasi token
  • bcrypt untuk hashing password

Database dan Struktur User

Untuk simplicity, kita gunakan in-memory storage berupa map (map[string]*User). Di dunia nyata, Anda bisa dengan mudah menggantinya dengan Postgres atau MongoDB.

go
1type User struct {
2    ID       string
3    Username string
4    Password string // Hashed!
5}

Secara sederhana, struktur storage-nya:

FieldTipeKeterangan
IDstringUUID
UsernamestringUnique, digunakan login
PasswordstringSudah di-hash dengan bcrypt

Skema GraphQL

Untuk kebutuhan registrasi dan login, cukup dua mutation sederhana:

graphql
 1type User {
 2    id: ID!
 3    username: String!
 4}
 5
 6type AuthPayload {
 7    token: String!
 8    user: User!
 9}
10
11type Mutation {
12    register(username: String!, password: String!): AuthPayload!
13    login(username: String!, password: String!): AuthPayload!
14}
15
16type Query {
17    me: User
18}

Proses Registrasi

Langkah-langkah:

  1. Input username & password user.
  2. Cek apakah username sudah dipakai.
  3. Hash password: bcrypt.
  4. Simpan user baru ke database.
  5. Generate JWT token.
  6. Kembalikan token & data user.
go
 1func (r *mutationResolver) Register(ctx context.Context, username string, password string) (*model.AuthPayload, error) {
 2    if _, exists := users[username]; exists {
 3        return nil, errors.New("username already exists")
 4    }
 5    hashed, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
 6    if err != nil {
 7        return nil, err
 8    }
 9    user := &User{
10        ID:       uuid.NewString(),
11        Username: username,
12        Password: string(hashed),
13    }
14    users[username] = user
15    token, err := generateJWT(user)
16    if err != nil {
17        return nil, err
18    }
19    return &model.AuthPayload{
20        Token: token,
21        User:  &model.User{ID: user.ID, Username: user.Username},
22    }, nil
23}

Proses Login

Simulasinya sangat mirip, hanya tahap validasi password diganti menjadi compare hash.

go
 1func (r *mutationResolver) Login(ctx context.Context, username string, password string) (*model.AuthPayload, error) {
 2    user, exists := users[username]
 3    if !exists {
 4        return nil, errors.New("invalid credentials")
 5    }
 6    if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
 7        return nil, errors.New("invalid credentials")
 8    }
 9    token, err := generateJWT(user)
10    if err != nil {
11        return nil, err
12    }
13    return &model.AuthPayload{
14        Token: token,
15        User:  &model.User{ID: user.ID, Username: user.Username},
16    }, nil
17}

Pembuatan & Validasi JWT

JWT dibuat saat register/login, dan di-validasi setiap kali akses endpoint yang protected.

Func generateJWT():

go
1func generateJWT(user *User) (string, error) {
2    claims := jwt.MapClaims{
3        "sub": user.ID,
4        "username": user.Username,
5        "exp": time.Now().Add(time.Hour * 24).Unix(),
6    }
7    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
8    return token.SignedString([]byte(SECRET_KEY))
9}

Func parseJWT():

go
 1func parseJWT(tokenStr string) (*User, error) {
 2    token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
 3        return []byte(SECRET_KEY), nil
 4    })
 5    if err != nil || !token.Valid {
 6        return nil, errors.New("invalid token")
 7    }
 8    claims, ok := token.Claims.(jwt.MapClaims)
 9    if !ok {
10        return nil, errors.New("invalid token claims")
11    }
12    username := claims["username"].(string)
13    user, exists := users[username]
14    if !exists {
15        return nil, errors.New("user not found")
16    }
17    return user, nil
18}

Middleware Proteksi Endpoint

Di gqlgen, kita inject user ke context, lalu di resolver tertentu, kita bisa cek authentication.

go
 1func AuthMiddleware() func(ctx context.Context) context.Context {
 2    return func(ctx context.Context) context.Context {
 3        token := extractBearerToken(ctx)
 4        if token == "" {
 5            return ctx
 6        }
 7        user, err := parseJWT(token)
 8        if err != nil {
 9            return ctx
10        }
11        return context.WithValue(ctx, "user", user)
12    }
13}

Kemudian, misalnya, di query me:

go
1func (r *queryResolver) Me(ctx context.Context) (*model.User, error) {
2    user := ctx.Value("user")
3    if user == nil {
4        return nil, errors.New("unauthenticated")
5    }
6    u := user.(*User)
7    return &model.User{ID: u.ID, Username: u.Username}, nil
8}

Diagram Alur

Mari ilustrasikan proses alur registrasi dan login menggunakan Mermaid:

MERMAID
sequenceDiagram
    participant Client
    participant Server

    Client->>Server: register(username, password)
    Server->>Server: cek username unik?
    alt username sudah ada
        Server-->>Client: error
    else username OK
        Server->>Server: hash password
        Server->>Server: simpan user ke DB
        Server->>Server: generate JWT
        Server-->>Client: {token, user}
    end
    
    Client->>Server: login(username, password)
    Server->>Server: ambil data user dari DB
    alt user tidak ditemukan
        Server-->>Client: error
    else ada user
        Server->>Server: verifikasi hash password
        alt invalid credentials
            Server-->>Client: error
        else sukses
            Server->>Server: generate JWT
            Server-->>Client: {token, user}
        end
    end

Simulasi Client

Misal mutation GraphQL yang di-post:

1. Registrasi

graphql
1mutation {
2  register(username: "andi", password: "rahasia") {
3    token
4    user { id username }
5  }
6}

Respon:

json
1{
2  "data": {
3    "register": {
4      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI... (JWT)",
5      "user": { "id": "c780...", "username": "andi" }
6    }
7  }
8}

2. Login

graphql
1mutation {
2  login(username: "andi", password: "rahasia") {
3    token
4    user { id username }
5  }
6}

3. Query Data Diri (Proteksi)

Sertakan header: Authorization: Bearer {token}

graphql
1query {
2  me { id username }
3}

Tabel Perbandingan: REST vs GraphQL + JWT

FiturREST + JWTGraphQL + JWT
Endpoint Registrasi/Login/register, /login1 endpoint (/graphql), mutation berbeda
Proteksi AuthMiddleware per routeMiddleware per field/resolver
ExtensibilitasNeeds new endpointTambahkan saja di schema
TransportJSONGraphQL Query

Catatan Keamanan

  • Jangan pernah menyimpan password tanpa hash.
  • JWT sebaiknya beri expiry (exp) yang wajar.
  • Gunakan HTTPS!
  • Validasi input user (XSS, SQLI, dll.)

Penutup

Dengan pattern seperti di atas, Anda bisa deploy aplikasi GraphQL + JWT authentication dengan cepat dan aman, memanfaatkan keunggulan type safety Go plus performa gqlgen. Di dunia nyata, Anda tinggal menambah koneksi ke Postgres atau MongoDB serta menerapkan security yang lebih ketat seperti rate limiting dan monitoring.

Semoga studi kasus sederhana registrasi & login JWT dengan gqlgen ini bisa menjadi fondasi implementasi authentication modern di project Anda berikutnya.

Happy hacking! 🚀


Kode Demo Lengkap:
github.com/youruser/gqlgen-jwt-example (dummy repository, silakan ganti dengan repo sendiri)

Artikel Terkait

💬 Komentar