LDAP issues
Closed this issue · 1 comments
trueeh commented
After some tests with 1.5.0-alpha.1 I noticed the following problems with LDAP:
- my LDAP doesn't return any passwords for security reasons, so the login always fails
- ldap_connect() with host and port is deprecated in PHP 8.3
- the warning prevents login (as described in issue #1540 )
I would recommend a "rebind" with the login user, then the LDAP-DN field can be omitted in the user management.
I use the host field for the URI (ldaps://...), the port field can be omitted, too.
I have adapted the check_login() for us like this, it would be great if you could find it useful and use it:
public function check_login(string $username, string $password): ?array
{
if (empty($username)) {
throw new InvalidArgumentException('No username value provided.');
}
$ldap_is_active = setting('ldap_is_active');
if (!$ldap_is_active) {
return null;
}
// Check LDAP environment and configuration
if (!extension_loaded('ldap')) {
throw new RuntimeException('The LDAP extension is not loaded.');
}
// Match user by username
$user = $this->CI->accounts->get_user_by_username($username);
if (empty($user['id'])) {
// user does not exist in easyappointments
return null;
}
// connect to LDAP server
$uri= setting('ldap_host');
$bind_dn = setting('ldap_user_dn');
$bind_password = setting('ldap_password');
$base_dn = setting('ldap_base_dn');
$filter = setting('ldap_filter');
$connection = ldap_connect($uri);
if (!$connection) {
throw new Exception('Could not connect to LDAP server: ' . ldap_error($connection));
}
ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($connection, LDAP_OPT_REFERRALS, 0); // We need this for doing an LDAP search.
$bind = ldap_bind($connection, $bind_dn, $bind_password);
if (!$bind) {
throw new Exception('LDAP bind failed: ' . ldap_error($connection));
}
// search user against the LDAP service
$filter = str_replace('{{KEYWORD}}', $username, $filter) ;
$result = ldap_search($connection, $base_dn, $filter);
if (!$result) {
return null;
}
$ldap_entry = ldap_first_entry($connection, $result);
if ($ldap_entry) {
$userDn = ldap_get_dn($connection, $ldap_entry);
$userBind = ldap_bind($connection, $userDn, $password);
if ($userBind) {
$role = $this->CI->roles_model->find($user['id_roles']);
$default_timezone = $this->CI->timezones->get_default_timezone();
return [
'user_id' => $user['id'],
'user_email' => $user['email'],
'username' => $username,
'timezone' => !empty($user['timezone']) ? $user['timezone'] : $default_timezone,
'language' => !empty($user['language']) ? $user['language'] : Config::LANGUAGE,
'role_slug' => $role['slug'],
];
}
}
return null;
}
alextselegidis commented
Hello!
Great, thanks for submitting this solution.
I adapted it to the app, but kept the "ldap_dn" value, as this will allow developers and admins sync users in different ways (e.g. via API, via SQL or even manually).
Apart from that it works like a charm 🚀
Alex Tselegidis, Easy!Appointments Creator Need a customization? Get a free quote! |