Skip to content

Commit ac36d84

Browse files
author
Gaetano Giunta
committed
Support 2 ldap servers for HA
1 parent 8e674f9 commit ac36d84

File tree

2 files changed

+71
-56
lines changed

2 files changed

+71
-56
lines changed

Adapter/LDAP/Client.php

Lines changed: 70 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ class Client implements ClientInterface
2121
protected $settings;
2222

2323
/**
24-
* @param LdapClientInterface $ldap
24+
* @param LdapClientInterface|LdapClientInterface[] $ldap
2525
* @param array $settings
2626
*
2727
* @todo document the settings
2828
*/
29-
public function __construct(LdapClientInterface $ldap, array $settings)
29+
public function __construct($ldap, array $settings)
3030
{
3131
$this->ldap = $ldap;
3232
$this->settings = $settings;
@@ -50,78 +50,92 @@ public function authenticateUser($username, $password)
5050
{
5151
if ($this->logger) $this->logger->info("Looking up remote user: '$username'");
5252

53-
try {
54-
$this->ldap->bind($this->settings['search_dn'], $this->settings['search_password']);
55-
$username = $this->ldap->escape($username, '', LDAP_ESCAPE_FILTER);
56-
$query = str_replace('{username}', $username, $this->settings['filter']);
57-
if (isset($this->settings['attributes']) && count($this->settings['attributes'])) {
58-
$search = $this->ldap->find($this->settings['base_dn'], $query, $this->settings['attributes']);
59-
} else {
60-
$search = $this->ldap->find($this->settings['base_dn'], $query);
61-
}
53+
$ldaps = is_array($this->ldap) ? array_values($this->ldap) : array($this->ldap);
54+
$i = 0;
6255

63-
} catch (ConnectionException $e) {
64-
if ($this->logger) $this->logger->error(sprintf('Connection error "%s"', $e->getMessage()));
56+
while (true) {
6557

66-
/// @todo shall we log an error ?
67-
throw new AuthenticationServiceException(sprintf('Connection error "%s"', $e->getMessage()), 0, $e);
68-
} catch (\Exception $e) {
69-
if ($this->logger) $this->logger->error(sprintf('Unexpected error "%s"', $e->getMessage()));
58+
$ldap = $ldaps[$i];
59+
$i++;
7060

71-
throw new AuthenticationServiceException(sprintf('Internal error "%s"', $e->getMessage()), 0, $e);
72-
}
61+
try {
62+
$ldap->bind($this->settings['search_dn'], $this->settings['search_password']);
63+
$username = $ldap->escape($username, '', LDAP_ESCAPE_FILTER);
64+
$query = str_replace('{username}', $username, $this->settings['filter']);
65+
if (isset($this->settings['attributes']) && count($this->settings['attributes'])) {
66+
$search = $ldap->find($this->settings['base_dn'], $query, $this->settings['attributes']);
67+
} else {
68+
$search = $ldap->find($this->settings['base_dn'], $query);
69+
}
7370

74-
if (!$search) {
75-
if ($this->logger) $this->logger->info("User not found");
71+
} catch (ConnectionException $e) {
72+
if ($this->logger) $this->logger->error(sprintf('Connection error "%s"', $e->getMessage()));
7673

77-
throw new BadCredentialsException(sprintf('User "%s" not found.', $username));
78-
}
74+
if ($i < count($ldaps)) {
75+
if ($this->logger) $this->logger->error("Connecting to ldap server $i");
76+
continue;
77+
}
7978

80-
if ($search['count'] > 1) {
81-
if ($this->logger) $this->logger->warning('More than one ldap account found for ' . $username);
79+
/// @todo shall we log an error ?
80+
throw new AuthenticationServiceException(sprintf('Connection error "%s"', $e->getMessage()), 0, $e);
81+
} catch (\Exception $e) {
82+
if ($this->logger) $this->logger->error(sprintf('Unexpected error "%s"', $e->getMessage()));
8283

83-
throw new AuthenticationServiceException('More than one user found');
84-
}
84+
throw new AuthenticationServiceException(sprintf('Internal error "%s"', $e->getMessage()), 0, $e);
85+
}
8586

86-
// always carry out this check, as the data is needed to log in
87-
if (!isset($this->settings['ldap_login_attribute']) || !isset($search[0][$this->settings['ldap_login_attribute']][0])) {
88-
if ($this->logger) $this->logger->info("Authentication failed for user: '$username', missing attribute used to log in to ldap: " . @$this->settings['ldap_login_attribute']);
87+
if (!$search) {
88+
if ($this->logger) $this->logger->info("User not found");
8989

90-
throw new AuthenticationServiceException('Invalid user profile: missing ldap attribute needed for log-in');
91-
}
90+
throw new BadCredentialsException(sprintf('User "%s" not found.', $username));
91+
}
9292

93-
try {
94-
$this->validateLdapResults($search[0]);
95-
} catch (\Exception $e) {
96-
if ($this->logger) $this->logger->warning("Invalid user profile for user: '$username': ".$e->getMessage());
93+
if ($search['count'] > 1) {
94+
if ($this->logger) $this->logger->warning('More than one ldap account found for ' . $username);
9795

98-
throw new AuthenticationServiceException('Invalid user profile: '.$e->getMessage());
99-
}
96+
throw new AuthenticationServiceException('More than one user found');
97+
}
10098

101-
if ($this->logger) $this->logger->info("Remote user found, attempting authentication for user: '$username'");
99+
// always carry out this check, as the data is needed to log in
100+
if (!isset($this->settings['ldap_login_attribute']) || !isset($search[0][$this->settings['ldap_login_attribute']][0])) {
101+
if ($this->logger) $this->logger->info("Authentication failed for user: '$username', missing attribute used to log in to ldap: " . @$this->settings['ldap_login_attribute']);
102102

103-
try {
104-
$this->ldap->bind($search[0][$this->settings['ldap_login_attribute']][0], $password);
105-
} catch (ConnectionException $e) {
106-
if ($this->logger) $this->logger->info("Authentication failed for user: '$username', bind failed: ".$e->getMessage());
107-
throw new BadCredentialsException('The presented password is invalid.');
108-
} catch (\Exception $e) {
109-
if ($this->logger) $this->logger->info("Authentication failed for user: '$username', unexpected ldap error: ".$e->getMessage());
110-
throw new AuthenticationServiceException('Unexpected exception: '.$e->getMessage());
111-
}
103+
throw new AuthenticationServiceException('Invalid user profile: missing ldap attribute needed for log-in');
104+
}
105+
106+
try {
107+
$this->validateLdapResults($search[0]);
108+
} catch (\Exception $e) {
109+
if ($this->logger) $this->logger->warning("Invalid user profile for user: '$username': ".$e->getMessage());
112110

113-
if ($this->logger) $this->logger->info("Authentication succeeded for user: '$username'");
111+
throw new AuthenticationServiceException('Invalid user profile: '.$e->getMessage());
112+
}
114113

115-
// allow ldap to give us back the actual login field to be used in eZ. It might be different because of dashes, spaces, case...
116-
if (isset($this->settings['login_attribute']) && isset($search[0][$this->settings['login_attribute']][0])) {
117-
if ($username != $search[0][$this->settings['login_attribute']][0]) {
118-
if ($this->logger) $this->logger->info("Renamed user '$username' to '{$search[0][$this->settings['login_attribute']][0]}'");
114+
if ($this->logger) $this->logger->info("Remote user found, attempting authentication for user: '$username'");
119115

120-
$username = $search[0][$this->settings['login_attribute']][0];
116+
try {
117+
$ldap->bind($search[0][$this->settings['ldap_login_attribute']][0], $password);
118+
} catch (ConnectionException $e) {
119+
if ($this->logger) $this->logger->info("Authentication failed for user: '$username', bind failed: ".$e->getMessage());
120+
throw new BadCredentialsException('The presented password is invalid.');
121+
} catch (\Exception $e) {
122+
if ($this->logger) $this->logger->info("Authentication failed for user: '$username', unexpected ldap error: ".$e->getMessage());
123+
throw new AuthenticationServiceException('Unexpected exception: '.$e->getMessage());
121124
}
122-
}
123125

124-
return new RemoteUser($search[0], $this->settings['email_attribute'], $username, $password);
126+
if ($this->logger) $this->logger->info("Authentication succeeded for user: '$username'");
127+
128+
// allow ldap to give us back the actual login field to be used in eZ. It might be different because of dashes, spaces, case...
129+
if (isset($this->settings['login_attribute']) && isset($search[0][$this->settings['login_attribute']][0])) {
130+
if ($username != $search[0][$this->settings['login_attribute']][0]) {
131+
if ($this->logger) $this->logger->info("Renamed user '$username' to '{$search[0][$this->settings['login_attribute']][0]}'");
132+
133+
$username = $search[0][$this->settings['login_attribute']][0];
134+
}
135+
}
136+
137+
return new RemoteUser($search[0], $this->settings['email_attribute'], $username, $password);
138+
}
125139
}
126140

127141
/**

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ Contributions are welcome :-)
7474
my.ldap_auth.client:
7575
class: Kaliop\IdentityManagementBundle\Adapter\LDAP\Client
7676
arguments:
77+
# NB: here you can pass in either one ldap client, or an array of clients, to achieve high-availability
7778
- "@my.ldap"
7879
-
7980
# the credentials used to serach the ldap

0 commit comments

Comments
 (0)