mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-02 21:40:14 +00:00
Users with 8-11 character passwords could not export/restore config backups because the export encryption requires 12+ character passphrases for security, but the password creation UI only enforced an 8-character minimum. This created a confusing UX where users with short passwords saw validation errors when trying to export backups, with the only solution being to use a custom passphrase or change their password. Root cause: - FirstRunSetup and ChangePasswordModal allowed 8+ char passwords - Config export/import requires 12+ char passphrases (backend validation) - The v4.26.4 fix added frontend validation that showed the mismatch - Users hit client-side validation before request was sent (no backend logs) This fix raises the minimum password length to 12 characters everywhere: - internal/auth/password.go: MinPasswordLength 8 → 12 - FirstRunSetup.tsx: validation and placeholder updated - ChangePasswordModal.tsx: validation, minLength, and help text updated - QuickSecuritySetup.tsx: validation and label updated Impact: - New users must create 12+ character passwords - Existing users with <12 char passwords are unaffected (can't detect from hash) - Those users will see the existing helpful error directing them to use custom passphrase for backups - "Use your login password" option now works for all future passwords This aligns password requirements across the system and eliminates the confusing mismatch between login credentials and backup encryption requirements. Related to #646 where user confirmed backups still failed in v4.26.5
50 lines
1.4 KiB
Go
50 lines
1.4 KiB
Go
package auth
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
const (
|
|
// BcryptCost is the cost factor for bcrypt hashing
|
|
// Higher values are more secure but slower
|
|
BcryptCost = 12
|
|
|
|
// MinPasswordLength is the minimum required password length
|
|
// Set to 12 to match the encryption requirement for config backups
|
|
MinPasswordLength = 12
|
|
)
|
|
|
|
// HashPassword generates a bcrypt hash from a plain text password
|
|
func HashPassword(password string) (string, error) {
|
|
bytes, err := bcrypt.GenerateFromPassword([]byte(password), BcryptCost)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(bytes), nil
|
|
}
|
|
|
|
// CheckPasswordHash compares a plain text password with a hash
|
|
func CheckPasswordHash(password, hash string) bool {
|
|
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
|
return err == nil
|
|
}
|
|
|
|
// IsPasswordHashed checks if a string looks like a bcrypt hash
|
|
func IsPasswordHashed(password string) bool {
|
|
// Bcrypt hashes start with $2a$, $2b$, or $2y$ and are 60 characters long
|
|
return strings.HasPrefix(password, "$2") && len(password) == 60
|
|
}
|
|
|
|
// ValidatePasswordComplexity checks if a password meets complexity requirements
|
|
func ValidatePasswordComplexity(password string) error {
|
|
if len(password) < MinPasswordLength {
|
|
return fmt.Errorf("password must be at least %d characters long", MinPasswordLength)
|
|
}
|
|
|
|
// That's it - let users choose their own passwords
|
|
// No annoying character type requirements
|
|
return nil
|
|
}
|