Skip to main content

Authentication & JWT Guide

Status: Documented | Last updated: 2025-12-18
Panduan lengkap untuk implementasi Authentication dan JWT Token lifecycle di MStore Backend.

Overview

MStore menggunakan JWT (JSON Web Token) dengan arsitektur Access Token + Refresh Token untuk autentikasi yang aman dan scalable.

Key Features

Multi-Method Login

Support login via Password, Google, dan Apple

Token Rotation

Refresh token rotation untuk keamanan maksimal

Session Security

Session tracking dengan audit trail

Revoke Support

Logout single session atau all sessions

Architecture


Implementation Details

1. JWT Payload Structure

Access token berisi informasi user yang diperlukan:
// internal/models/jwt.go
type JwtClaims struct {
    UserID       uint64 `json:"userId"`
    Email        string `json:"email"`
    Role         string `json:"role"`
    Roles        []string `json:"roles"`
    MerchantID   string `json:"merchantId"`
    BranchID     string `json:"branchId"`
    SessionID    string `json:"sessionId"`
    LoginMethod  string `json:"loginMethod"`
    LoginAt      int64  `json:"loginAt"`
    jwt.StandardClaims
}

2. Token Configuration

// internal/config/config.go
type SystemConfig struct {
    JwtSecret   string `env:"SYSTEM_JWT_SECRET"`
    JwtExpired  int    `env:"SYSTEM_EXPIRED_JWT" envDefault:"60"` // minutes
}

3. Auth Middleware

// internal/middleware/auth.go
func AuthMiddleware(c *fiber.Ctx) error {
    // Parse Bearer token
    authHeader := c.Get("Authorization")
    token := strings.TrimPrefix(authHeader, "Bearer ")

    // Validate JWT
    claims, err := utils_jwt.CheckJWTValid(config.Apps.System.JwtSecret, token)
    if err != nil {
        return c.Status(401).JSON(fiber.Map{
            "error": "Unauthorized"
        })
    }

    // Set claims to context
    c.Locals("user_session", claims)
    return c.Next()
}

API Endpoints

Login

POST /api/v2/core/auth/login
Content-Type: application/json

{
  "email": "[email protected]",
  "password": "your_password",
  "login_method": "password"  // password | google | apple
}

Refresh Token

POST /api/v2/core/auth/refresh-token
Content-Type: application/json

{
  "refresh_token": "your_refresh_token"
}
Refresh token menggunakan hashed rotation - setiap kali di-refresh, token lama akan di-invalidate dan token baru digenerate.

Logout

POST /api/v2/core/auth/logout
Authorization: Bearer {access_token}

Logout All Sessions

POST /api/v2/core/auth/logout-all
Authorization: Bearer {access_token}

Middleware Stack

MStore Backend menggunakan middleware chain untuk security:
OrderMiddlewareFilePurpose
1RequestIDMiddlewareauth.goCorrelation ID untuk tracing
2AuditLogMiddlewareaudit_log.goAudit trail logging
3RBACEnforcerMiddlewarerbac_enforcer.goRole-based access control
4AuthMiddlewareauth.goJWT validation
5RateLimitRefreshByIPratelimit.goRate limiting (10 req/min)

Session Activity Tracking

Setiap login dan aktivitas session disimpan untuk audit:
-- session_activity table
| Column       | Type      | Description |
|--------------|-----------|-------------|
| id           | bigint    | Primary key |
| user_id      | bigint    | FK to users |
| session_id   | varchar   | UUID session |
| login_method | varchar   | password/google/apple |
| login_time   | timestamp | Login timestamp |
| ip_address   | varchar   | Client IP |
| user_agent   | text      | Browser/Device info |

Security Best Practices

Jangan pernah menyimpan JwtSecret di source code. Gunakan environment variables.
  1. Token Expiry: Access token: 60 menit, Refresh token: 7 hari
  2. Hashed Storage: Refresh token disimpan sebagai hash di database
  3. Token Rotation: Setiap refresh menghasilkan token baru
  4. Session Revocation: Support logout single/all sessions
  5. Rate Limiting: 10 request/menit per IP untuk refresh endpoint


Jira References