mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-15 09:49:48 +00:00
- Remove overly restrictive password complexity requirements (now only 8+ chars) - Fix Change Password section not appearing in Settings > Security - Fix logout sometimes showing setup page instead of login page - Remove misleading desktop notifications option from first-run setup - Improve rate limiting on authentication endpoints - Fix sensitive data appearing in logs (passwords, tokens) - Enhance file permissions for sensitive files (0600) - Fix WebSocket origin validation defaults - Add password complexity validation for setup - Improve CSRF token handling after server restarts - Fix security status API using wrong fetch client - Add logout race condition prevention Security improvements: - No credential leakage in logs - Proper bcrypt password hashing - Session management enhancements - Rate limiting on all auth endpoints - Secure file permissions on sensitive data
59 lines
No EOL
1.7 KiB
Go
59 lines
No EOL
1.7 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
|
|
MinPasswordLength = 8
|
|
)
|
|
|
|
// 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
|
|
}
|
|
|
|
// MigratePassword takes a password that might be plain text or hashed
|
|
// and returns a properly hashed version
|
|
func MigratePassword(password string) (string, error) {
|
|
if IsPasswordHashed(password) {
|
|
// Already hashed, return as-is
|
|
return password, nil
|
|
}
|
|
// Plain text password, hash it
|
|
return HashPassword(password)
|
|
}
|
|
|
|
// 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
|
|
} |