ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilAuthProviderLDAP.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
27 {
29  private string $migration_account = '';
30  private bool $force_new_account = false;
31 
32  public function __construct(ilAuthCredentials $credentials, int $a_server_id = 0)
33  {
34  parent::__construct($credentials);
35  $this->initServer($a_server_id);
36  }
37 
38  public function getServer(): ilLDAPServer
39  {
40  return $this->server;
41  }
42 
46  public function doAuthentication(ilAuthStatus $status): bool
47  {
48  try {
49  // bind
50  $query = new ilLDAPQuery($this->getServer());
51  $query->bind();
52  } catch (ilLDAPQueryException $e) {
53  $this->getLogger()->error('Cannot bind to LDAP server... ' . $e->getMessage());
54  $this->handleAuthenticationFail($status, 'auth_err_ldap_exception');
55  return false;
56  }
57  try {
58  // Read user data, which does ensure a sucessful authentication.
59  $users = $query->fetchUser(
60  $this->getCredentials()->getUsername()
61  );
62 
63  if (!$users) {
64  $this->handleAuthenticationFail($status, 'err_wrong_login');
65  return false;
66  }
67  if (!trim($this->getCredentials()->getPassword())) {
68  $this->handleAuthenticationFail($status, 'err_wrong_login');
69  return false;
70  }
71  if (!array_key_exists($this->changeKeyCase($this->getCredentials()->getUsername()), $users)) {
72  $this->getLogger()->warning('Cannot find user: ' . $this->changeKeyCase($this->getCredentials()->getUsername()));
73  $this->handleAuthenticationFail($status, 'auth_err_ldap_exception');
74  return false;
75  }
76 
77  // check group membership
78  if (!$query->checkGroupMembership(
79  $this->getCredentials()->getUsername(),
80  $users[$this->changeKeyCase($this->getCredentials()->getUsername())]
81  )) {
82  $this->handleAuthenticationFail($status, 'err_wrong_login');
83  return false;
84  }
85  } catch (ilLDAPQueryException $e) {
86  $this->getLogger()->error('Cannot fetch LDAP user data... ' . $e->getMessage());
87  $this->handleAuthenticationFail($status, 'auth_err_ldap_exception');
88  return false;
89  }
90  try {
91  // now bind with login credentials
92  $query->bind(
94  $users[$this->changeKeyCase($this->getCredentials()->getUsername())]['dn'],
95  $this->getCredentials()->getPassword()
96  );
97  } catch (ilLDAPQueryException $e) {
98  $this->handleAuthenticationFail($status, 'err_wrong_login');
99  return false;
100  }
101 
102  // authentication success update profile
103  return $this->updateAccount($status, $users[$this->changeKeyCase($this->getCredentials()->getUsername())]);
104  }
105 
109  protected function updateAccount(ilAuthStatus $status, array $user): bool
110  {
111  $user = array_change_key_case($user, CASE_LOWER);
112  $this->getLogger()->dump($user, ilLogLevel::DEBUG);
113 
114  $sync = new ilLDAPUserSynchronisation(
115  'ldap_' . $this->getServer()->getServerId(),
116  $this->getServer()->getServerId()
117  );
118  $sync->setExternalAccount($this->getCredentials()->getUsername());
119  $sync->setUserData($user);
120  $sync->forceCreation($this->force_new_account);
121 
122  try {
123  $internal_account = $sync->sync();
124  $this->getLogger()->debug('Internal account: ' . $internal_account);
125  } catch (UnexpectedValueException $e) {
126  $this->getLogger()->info('Login failed with message: ' . $e->getMessage());
127  $this->handleAuthenticationFail($status, 'err_wrong_login');
128  return false;
130  $this->handleAuthenticationFail($status, 'err_auth_ldap_failed');
131  return false;
133  // No syncronisation allowed => create Error
134  $this->getLogger()->info('Login failed with message: ' . $e->getMessage());
135  $this->handleAuthenticationFail($status, 'err_auth_ldap_no_ilias_user');
136  return false;
138  // Account migration required
139  $this->setExternalAccountName($this->getCredentials()->getUsername());
140  $this->getLogger()->info('Authentication failed: account migration required for external account: ' . $this->getCredentials()->getUsername());
142  return false;
143  }
145  $status->setAuthenticatedUserId(ilObjUser::_lookupId($internal_account));
146  return true;
147  }
148 
149  protected function initServer(int $a_server_id): void
150  {
151  $this->server = new ilLDAPServer($a_server_id);
152  }
153 
157  public function createNewAccount(ilAuthStatus $status): void
158  {
159  $this->force_new_account = true;
160 
161  try {
162  $query = new ilLDAPQuery($this->getServer());
163  $query->bind();
164  } catch (ilLDAPQueryException $e) {
165  $this->getLogger()->error('Cannot bind to LDAP server... ' . $e->getMessage());
166  $this->handleAuthenticationFail($status, 'auth_err_ldap_exception');
167  return;
168  }
169  try {
170  // fetch user
171  $users = $query->fetchUser(
172  $this->getCredentials()->getUsername()
173  );
174  if (!$users) {
175  $this->handleAuthenticationFail($status, 'err_wrong_login');
176  return;
177  }
178  if (!array_key_exists($this->changeKeyCase($this->getCredentials()->getUsername()), $users)) {
179  $this->handleAuthenticationFail($status, 'err_wrong_login');
180  return;
181  }
182  } catch (ilLDAPQueryException $e) {
183  $this->getLogger()->error('Cannot fetch LDAP user data... ' . $e->getMessage());
184  $this->handleAuthenticationFail($status, 'auth_err_ldap_exception');
185  return;
186  }
187 
188  // authentication success update profile
189  $this->updateAccount($status, $users[$this->changeKeyCase($this->getCredentials()->getUsername())]);
190  }
191 
195  public function migrateAccount(ilAuthStatus $status): void
196  {
197  $this->force_new_account = true;
198 
199  try {
200  $query = new ilLDAPQuery($this->getServer());
201  $query->bind();
202  } catch (ilLDAPQueryException $e) {
203  $this->getLogger()->error('Cannot bind to LDAP server... ' . $e->getMessage());
204  $this->handleAuthenticationFail($status, 'auth_err_ldap_exception');
205  return;
206  }
207 
208  $users = $query->fetchUser($this->getCredentials()->getUsername());
209  $this->updateAccount($status, $users[$this->changeKeyCase($this->getCredentials()->getUsername())]);
210  }
211 
215  public function getTriggerAuthMode(): string
216  {
217  return ilAuthUtils::AUTH_LDAP . '_' . $this->getServer()->getServerId();
218  }
219 
223  public function getUserAuthModeName(): string
224  {
225  return 'ldap_' . $this->getServer()->getServerId();
226  }
227 
231  public function getExternalAccountName(): string
232  {
234  }
235 
236  public function setExternalAccountName(string $a_name): void
237  {
238  $this->migration_account = $a_name;
239  }
240 
245  protected function changeKeyCase(string $a_string)
246  {
247  return array_key_first(array_change_key_case([$a_string => $a_string]));
248  }
249 }
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Interface of auth credentials.
updateAccount(ilAuthStatus $status, array $user)
Update Account.
createNewAccount(ilAuthStatus $status)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Synchronization of user accounts used in auth container ldap, cas,...
static _lookupId($a_user_str)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
changeKeyCase(string $a_string)
Change case similar to array_change_key_case, to avoid further encoding problems. ...
handleAuthenticationFail(ilAuthStatus $status, string $a_reason)
Handle failed authentication.
Base class for authentication providers (ldap, apache, ...)
__construct(ilAuthCredentials $credentials, int $a_server_id=0)
setStatus(int $a_status)
Set auth status.
doAuthentication(ilAuthStatus $status)
ilAuthCredentials $credentials
$query
getLogger()
Get logger.
migrateAccount(ilAuthStatus $status)
__construct(Container $dic, ilPlugin $plugin)
setAuthenticatedUserId(int $a_id)
setExternalAccountName(string $a_name)
Auth status implementation.
const STATUS_ACCOUNT_MIGRATION_REQUIRED