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",
})
}