Skip to main content

Password Validation

Dokumentasi utility functions untuk validasi dan manajemen password.

Overview

Package utils menyediakan functions untuk validasi password dan pengecekan expiration password.

Functions

IsPasswordValid

Memvalidasi apakah password memenuhi kriteria keamanan.

func IsPasswordValid(KataSandi string) bool

Validation Rules

RuleDeskripsiRegex
Minimum LengthMinimal 8 karakterlen >= 8
LowercaseMinimal 1 huruf kecil[a-z]
UppercaseMinimal 1 huruf besar[A-Z]
DigitMinimal 1 angka[0-9]
Special CharacterMinimal 1 karakter spesial[\W_]

Example

// ✅ Valid passwords
utils.IsPasswordValid("Password1!") // true
utils.IsPasswordValid("MyP@ssw0rd") // true
utils.IsPasswordValid("Str0ng#Pass") // true

// ❌ Invalid passwords
utils.IsPasswordValid("password") // false - no uppercase, no digit, no special
utils.IsPasswordValid("PASSWORD1") // false - no lowercase, no special
utils.IsPasswordValid("Pass1!") // false - less than 8 characters
utils.IsPasswordValid("Password1") // false - no special character

Implementation

func IsPasswordValid(KataSandi string) bool {
if len(KataSandi) < 8 {
return false
}

hasLower := regexp.MustCompile(`[a-z]`).MatchString(KataSandi)
hasUpper := regexp.MustCompile(`[A-Z]`).MatchString(KataSandi)
hasDigit := regexp.MustCompile(`[0-9]`).MatchString(KataSandi)
hasSpecial := regexp.MustCompile(`[\W_]`).MatchString(KataSandi)

return hasLower && hasUpper && hasDigit && hasSpecial
}

CheckUmurSandi

Mengecek apakah password sudah expired dan mengirim notifikasi warning.

func CheckUmurSandi(result *models.Auth, token string) bool

Parameters

ParameterTypeDeskripsi
result*models.AuthData auth pengguna
tokenstringAuthorization token untuk notifikasi

Return

  • true - Password sudah expired
  • false - Password masih valid

Password Lifecycle

┌─────────────────────────────────────────────────────────────────────────────┐
│ PASSWORD LIFECYCLE │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Created/Updated ◀────────────────── 6 Months ──────────────────▶ Expired │
│ │ │ │
│ │ ┌─────────────────┐ │ │
│ │ │ WARNING ZONE │ │ │
│ │ │ (10 days) │ │ │
│ │ │ │ │ │
│ │ │ ┌───────────┐ │ │ │
│ │ │ │Notification│ │ │ │
│ │ │ │ Sent │ │ │ │
│ │ │ └───────────┘ │ │ │
│ │ └─────────────────┘ │ │
│ ▼ ▲ ▼ │
│ ┌─────────┐ │ ┌─────────┐ │
│ │ VALID │───────────────────────┼──────────────────────────│ EXPIRED │ │
│ └─────────┘ │ └─────────┘ │
│ │ │
│ Day 170 (10 days before expiry) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

Logic Flow

  1. Password belum pernah di-update → Set UpdateAtSandi ke waktu sekarang, return false
  2. Dalam warning zone (10 hari sebelum expired) → Kirim notifikasi, return false
  3. Password expired (> 6 bulan) → Return true
  4. Password masih valid → Return false

Example Usage

func Login(c *gin.Context) {
// ... authenticate user

// Check password expiration
isExpired := utils.CheckUmurSandi(&authResult, c.GetHeader("Authorization"))

if isExpired {
c.JSON(http.StatusUnauthorized, gin.H{
"code": 401,
"status": false,
"message": "Password expired. Please reset your password.",
"data": gin.H{
"requirePasswordReset": true,
},
})
return
}

// Continue with login...
}

Password Policy Summary

PolicyValue
Minimum Length8 characters
Requires LowercaseYes
Requires UppercaseYes
Requires DigitYes
Requires Special CharacterYes
Expiration Period6 months
Warning Period10 days before expiry

Special Characters Reference

Karakter spesial yang diterima (regex [\W_]):

! @ # $ % ^ & * ( ) - _ = + [ ] { } | \ ; : ' " , . < > / ? ` ~

Integration Example

func ChangePassword(c *gin.Context) {
var req dto.ChangePasswordRequest

if err := c.ShouldBindJSON(&req); err != nil {
helpers.SendError(c, helpers.NewBadRequest("Invalid request"))
return
}

// Validate new password
if !utils.IsPasswordValid(req.NewPassword) {
helpers.SendError(c, helpers.NewBadRequest(
"Password must be at least 8 characters with uppercase, lowercase, digit, and special character"))
return
}

// Validate password confirmation
if req.NewPassword != req.ConfirmPassword {
helpers.SendError(c, helpers.NewBadRequest("Password confirmation does not match"))
return
}

// Update password...
user.KataSandi = hashPassword(req.NewPassword)
user.UpdateAtSandi = time.Now()

repository.Update(&user)

c.JSON(http.StatusOK, gin.H{
"code": 200,
"status": true,
"message": "Password changed successfully",
})
}