Add LDAP authentication
- LDAP bind + search auth with auto-create local user - Falls back to local auth if LDAP not configured or fails - Configurable via MH_LDAP_* environment variables - Supports ldap:// and ldaps:// with optional TLS skip - go-ldap/ldap/v3 dependency added
This commit is contained in:
@@ -90,7 +90,39 @@ func (s *Server) handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||
err := s.db.QueryRow(
|
||||
"SELECT id, password_hash, is_admin, totp_secret FROM users WHERE email = ?", req.Email,
|
||||
).Scan(&id, &hash, &isAdmin, &totpSecret)
|
||||
if err != nil || !auth.CheckPassword(hash, req.Password) {
|
||||
|
||||
localAuthOK := err == nil && auth.CheckPassword(hash, req.Password)
|
||||
|
||||
// Try LDAP if local auth failed
|
||||
if !localAuthOK {
|
||||
ldapCfg := auth.LDAPConfigFromEnv()
|
||||
if ldapCfg != nil {
|
||||
email, displayName, ldapErr := auth.LDAPAuth(ldapCfg, req.Email, req.Password)
|
||||
if ldapErr == nil {
|
||||
// LDAP success — find or create local user
|
||||
err2 := s.db.QueryRow(
|
||||
"SELECT id, password_hash, is_admin, totp_secret FROM users WHERE email = ?", email,
|
||||
).Scan(&id, &hash, &isAdmin, &totpSecret)
|
||||
if err2 != nil {
|
||||
// Auto-create user from LDAP
|
||||
id = uuid.New().String()
|
||||
username := displayName
|
||||
if username == "" {
|
||||
username = req.Email
|
||||
}
|
||||
s.db.Exec(
|
||||
"INSERT INTO users (id, username, email, password_hash, is_admin) VALUES (?, ?, ?, ?, 0)",
|
||||
id, username, email, "ldap",
|
||||
)
|
||||
files.EnsureUserDir(s.dataDir, id)
|
||||
totpSecret = nil
|
||||
}
|
||||
localAuthOK = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !localAuthOK {
|
||||
recordLoginAttempt(ip)
|
||||
writeJSON(w, 401, map[string]string{"error": "invalid credentials"})
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user