ILIAS  release_8 Revision v8.24
class.ilAuthProviderECS.php
Go to the documentation of this file.
1<?php
2
18declare(strict_types=1);
19
20use ILIAS\Refinery\Factory as Refinery;
21use ILIAS\HTTP\Services as HTTPServices;
22
29{
34 private Refinery $refinery;
35 private HTTPServices $http;
38
39 protected ?int $mid = null;
40 protected ?string $abreviation = null;
41
44
45
51 {
53
54 global $DIC;
55
56 $this->clientIniFile = $DIC->clientIni();
57 $this->rbacAdmin = $DIC->rbac()->admin();
58 $this->setting = $DIC->settings();
59 $this->lng = $DIC->language();
60 $this->lng->loadLanguageModule('ecs');
61 $this->http = $DIC->http();
62 $this->refinery = $DIC->refinery();
63 $this->authSession = $DIC['ilAuthSession'];
64 $this->ctrl = $DIC->ctrl();
65
66 $this->initECSServices();
67 }
68
72 public function getAbreviation(): string
73 {
74 return $this->abreviation;
75 }
76
80 public function getMID(): int
81 {
82 return $this->mid;
83 }
84
85 public function setMID(int $a_mid): void
86 {
87 $this->mid = $a_mid;
88 }
89
93 public function setCurrentServer(ilECSSetting $server): void
94 {
95 $this->currentServer = $server;
96 }
97
102 {
104 }
105
110 {
111 return $this->servers;
112 }
113
114
118 public function doAuthentication(\ilAuthStatus $status): bool
119 {
120 $this->getLogger()->debug('Starting ECS authentication');
121 if (!$this->getServerSettings()->activeServerExists()) {
122 $this->getLogger()->warning('No active ecs server found. Aborting');
123 $this->handleAuthenticationFail($status, 'err_wrong_login');
124 return false;
125 }
126
127 // Iterate through all active ecs instances
128 foreach ($this->getServerSettings()->getServers(ilECSServerSettings::ACTIVE_SERVER) as $server) {
129 $this->setCurrentServer($server);
130 if ($this->validateHash()) {
131 return $this->handleLoginByAuthMode($status);
132 }
133 }
134 $this->getLogger()->warning('Could not validate ecs hash for any active server.');
135 $this->handleAuthenticationFail($status, 'err_wrong_login');
136 return false;
137 }
138
144 {
145 $is_external_account = false;
146 if ($this->http->wrapper()->query()->has('ecs_external_account')) {
147 $is_external_account = $this->http->wrapper()->query()->retrieve(
148 'ecs_external_account',
149 $this->refinery->kindlyTo()->bool()
150 );
151 }
152 $redirection_target = '';
153 if ($this->http->wrapper()->query()->has('target')) {
154 $redirection_target = $this->http->wrapper()->query()->retrieve(
155 'target',
156 $this->refinery->kindlyTo()->string()
157 );
158 }
159 $part_settings = new ilECSParticipantSetting(
160 $this->getCurrentServer()->getServerId(),
161 $this->getMID()
162 );
163 if ($this->resumeCurrentSession()) {
164 $this->getLogger()->debug('Continuing current user session');
166 $status->setAuthenticatedUserId($this->authSession->getUserId());
167 return true;
168 }
169 if (
170 $is_external_account &&
171 $part_settings->getIncomingAuthType() === ilECSParticipantSetting::INCOMING_AUTH_TYPE_LOGIN_PAGE
172 ) {
173 $this->getLogger()->info('ILIAS login page authentication required.');
174 ilSession::set('success', $this->lng->txt('ecs_login_success_ilias'));
176 $this->ctrl->redirectToURL('login.php?target=' . $redirection_target);
177 return false;
178 }
179 if (
180 $is_external_account &&
181 $part_settings->getIncomingAuthType() === ilECSParticipantSetting::INCOMING_AUTH_TYPE_SHIBBOLETH
182 ) {
183 $this->getLogger()->info('Redirect to shibboleth authentication');
185 $this->ctrl->redirectToURL('shib_login.php?target=' . $redirection_target);
186 }
187 if ($part_settings->areIncomingLocalAccountsSupported()) {
188 // handle successful authentication
189 $new_usr_id = $this->handleLogin();
190 $this->getLogger()->info('ECS authentication successful.');
192 $status->setAuthenticatedUserId($new_usr_id);
193 return true;
194 }
195 $this->handleAuthenticationFail($status, 'err_wrong_login');
196 return false;
197 }
198
199 protected function resumeCurrentSession(): bool
200 {
201 $session_user_id = $this->authSession->getUserId();
202 if (!$session_user_id || $session_user_id === ANONYMOUS_USER_ID) {
203 $this->getLogger()->debug('No valid session found');
204 $this->authSession->setAuthenticated(false, ANONYMOUS_USER_ID);
205 return false;
206 }
207 $session_ext_account = ilObjUser::_lookupExternalAccount($session_user_id);
208 $user = new ilECSUser($this->http->request()->getQueryParams());
209 $this->getLogger()->debug('ECS user name: ' . $user->getLogin());
210 $this->getLogger()->debug('Session external account: ' . $session_ext_account);
211 if (!$session_ext_account || strcmp($user->getLogin(), $session_ext_account) !== 0) {
212 $this->getLogger()->debug('No matching session found. Terminating current user session.');
213 $this->authSession->setAuthenticated(false, ANONYMOUS_USER_ID);
214 return false;
215 }
216 // assign to ECS global role
217 $this->rbacAdmin->assignUser($this->getCurrentServer()->getGlobalRole(), $this->authSession->getUserId());
218 return true;
219 }
220
221
225 public function handleLogin()
226 {
227 $user = new ilECSUser($this->http->request()->getQueryParams());
228
229 if (!$usr_id = ilObject::_lookupObjIdByImportId($user->getImportId())) {
230 $username = $this->createUser($user);
231 } else {
232 $username = $this->updateUser($user, $usr_id);
233 }
234
235 // set user imported
236 $import = new ilECSImport($this->getCurrentServer()->getServerId(), $usr_id);
237 $import->save();
238
239 // Store remote user data
240 $remoteUserRepository = new ilECSRemoteUserRepository();
241 $remoteUserRepository->createIfNotExisting(
242 $this->getCurrentServer()->getServerId(),
243 $this->getMID(),
244 ilObjUser::_lookupId($username),
245 $user->getImportId()
246 );
247
248 $this->getLogger()->info('Current user is: ' . $username);
249
250 return ilObjUser::_lookupId($username);
251 }
252
253 public function initRemoteUserWithRemoteId(): void
254 {
255 $user = new ilECSUser($this->http->request()->getQueryParams());
256
257 // Store remote user data
258 $remoteUserRepository = new ilECSRemoteUserRepository();
259 $remoteUserRepository->createIfRemoteUserNotExisting(
260 $this->getCurrentServer()->getServerId(),
261 $this->getMID(),
262 0,
263 $user->getLogin()
264 );
265 }
266
270 public function validateHash(): bool
271 {
272 // fetch hash
273 $hash = "";
274 if ($this->http->wrapper()->query()->has('ecs_hash')) {
275 $hash = $this->http->wrapper()->query()->retrieve(
276 'ecs_hash',
277 $this->refinery->kindlyTo()->string()
278 );
279 }
280 if ($this->http->wrapper()->query()->has('ecs_hash_url')) {
281 $hashurl = urldecode(
282 $this->http->wrapper()->query()->retrieve(
283 'ecs_hash_url',
284 $this->refinery->kindlyTo()->string()
285 )
286 );
287 $hash = basename(parse_url($hashurl, PHP_URL_PATH));
288 }
289
290 $this->getLogger()->info('Using ecs hash: ' . $hash);
291 // Check if hash is valid ...
292 try {
293 $connector = new ilECSConnector($this->getCurrentServer());
294 $res = $connector->getAuth($hash);
295 $auths = $res->getResult();
296
297 $this->getLogger()->dump($auths, ilLogLevel::DEBUG);
298
299 if ($auths->pid) {
300 try {
301 $reader = ilECSCommunityReader::getInstanceByServerId($this->getCurrentServer()->getServerId());
302 foreach ($reader->getParticipantsByPid($auths->pid) as $participant) {
303 if ($participant->getOrganisation() instanceof \ilECSOrganisation) {
304 $this->abreviation = $participant->getOrganisation()->getAbbreviation();
305 break;
306 }
307 }
308 if (!$this->abreviation) {
309 $this->abreviation = $auths->abbr;
310 }
311 } catch (Exception $e) {
312 $this->getLogger()->warning('Authentication failed with message: ' . $e->getMessage());
313 return false;
314 }
315 } else {
316 $this->abreviation = $auths->abbr;
317 }
318
319 $this->getLogger()->debug('Got abbreviation: ' . $this->abreviation);
320 } catch (ilECSConnectorException $e) {
321 $this->getLogger()->warning('Authentication failed with message: ' . $e->getMessage());
322 return false;
323 }
324
325 // read current mid
326 try {
327 $connector = new ilECSConnector($this->getCurrentServer());
328 $details = $connector->getAuth($hash, true);
329
330 $this->getLogger()->dump($details, ilLogLevel::DEBUG);
331 $this->getLogger()->debug('Token create for mid: ' . $details->getFirstSender());
332
333 $this->setMID($details->getFirstSender());
334 } catch (ilECSConnectorException $e) {
335 $this->getLogger()->warning('Receiving mid failed with message: ' . $e->getMessage());
336 return false;
337 }
338 return true;
339 }
340
341
345 private function initECSServices(): void
346 {
347 $this->servers = ilECSServerSettings::getInstance();
348 }
349
353 protected function createUser(ilECSUser $user): string
354 {
355 $userObj = new ilObjUser();
356 $userObj->setOwner(SYSTEM_USER_ID);
357
358 $local_user = ilAuthUtils::_generateLogin($this->getAbreviation() . '_' . $user->getLogin());
359
360 $newUser["login"] = $local_user;
361 $newUser["firstname"] = $user->getFirstname();
362 $newUser["lastname"] = $user->getLastname();
363 $newUser['email'] = $user->getEmail();
364 $newUser['institution'] = $user->getInstitution();
365
366 // set "plain md5" password (= no valid password)
367 $newUser["passwd"] = "";
368 $newUser["passwd_type"] = ilObjUser::PASSWD_CRYPTED;
369
370 $newUser["auth_mode"] = "ecs";
371 $newUser["profile_incomplete"] = 0;
372
373 // system data
374 $userObj->assignData($newUser);
375 $userObj->setTitle($userObj->getFullname());
376 $userObj->setDescription($userObj->getEmail());
377
378 // set user language to system language
379 $userObj->setLanguage($this->setting->get("language"));
380
381 // Time limit
382 $userObj->setTimeLimitOwner(7);
383 $userObj->setTimeLimitUnlimited(false);
384 $userObj->setTimeLimitFrom(time() - 5);
385 $userObj->setTimeLimitUntil(time() + (int) $this->clientIniFile->readVariable("session", "expire"));
386
387 // Create user in DB
388 $userObj->setOwner(6);
389 $userObj->create();
390 $userObj->setActive(true);
391 $userObj->saveAsNew();
392 $userObj->updateOwner();
393 $userObj->writePrefs();
394
395 if ($this->getCurrentServer()->getGlobalRole()) {
396 $this->rbacAdmin->assignUser($this->getCurrentServer()->getGlobalRole(), $userObj->getId());
397 }
398 ilObject::_writeImportId($userObj->getId(), $user->getImportId());
399
400 $this->getLogger()->info('Created new remote user with usr_id: ' . $user->getImportId());
401
402 // Send Mail
403 #$this->sendNotification($userObj);
404 $this->resetMailOptions($userObj->getId());
405
406 return $userObj->getLogin();
407 }
408
412 protected function updateUser(ilECSUser $user, int $a_local_user_id): string
413 {
414 $user_obj = new ilObjUser($a_local_user_id);
415 $user_obj->setFirstname($user->getFirstname());
416 $user_obj->setLastname($user->getLastname());
417 $user_obj->setEmail($user->getEmail());
418 $user_obj->setInstitution($user->getInstitution());
419 $user_obj->setActive(true);
420
421 $until = $user_obj->getTimeLimitUntil();
422
423 if ($until < (time() + (int) $this->clientIniFile->readVariable('session', 'expire'))) {
424 $user_obj->setTimeLimitFrom(time() - 60);
425 $user_obj->setTimeLimitUntil(time() + (int) $this->clientIniFile->readVariable("session", "expire"));
426 }
427 $user_obj->update();
428 $user_obj->refreshLogin();
429
430 if ($this->getCurrentServer()->getGlobalRole()) {
431 $this->rbacAdmin->assignUser(
432 $this->getCurrentServer()->getGlobalRole(),
433 $user_obj->getId()
434 );
435 }
436
437 $this->resetMailOptions($a_local_user_id);
438
439 $this->getLogger()->debug('Finished update of remote user with usr_id: ' . $user->getImportId());
440 return $user_obj->getLogin();
441 }
442
447 protected function resetMailOptions(int $a_usr_id): void
448 {
449 $options = new ilMailOptions($a_usr_id);
450 $options->setIncomingType(ilMailOptions::INCOMING_LOCAL);
451 $options->updateOptions();
452 }
453}
Builds data types.
Definition: Factory.php:21
Class Services.
Definition: Services.php:38
Auth prvider for ecs auth.
doAuthentication(\ilAuthStatus $status)
Try ecs authentication.
__construct(\ilAuthCredentials $credentials)
Constructor.
resetMailOptions(int $a_usr_id)
Reset mail options to "local only".
getServerSettings()
Get server settings.
setCurrentServer(ilECSSetting $server)
Set current server.
getAbreviation()
get abbreviation
createUser(ilECSUser $user)
create new user
updateUser(ilECSUser $user, int $a_local_user_id)
update existing user
initECSServices()
Init ECS Services.
handleLogin()
Called from base class after successful login.
handleLoginByAuthMode(ilAuthStatus $status)
Redirects to shibboleth login; to standard login page for LDAP based authentication or authenticates/...
getCurrentServer()
Get current server.
ilECSServerSettings $servers
validateHash()
Validate ECS hash.
Base class for authentication providers (ldap, apache, ...)
getLogger()
Get logger.
handleAuthenticationFail(ilAuthStatus $status, string $a_reason)
Handle failed authentication.
ilAuthCredentials $credentials
Auth status implementation.
setStatus(int $a_status)
Set auth status.
static _generateLogin(string $a_login)
generate free login by starting with a default string and adding postfix numbers
static getInstanceByServerId(int $a_server_id)
Get instance by server id.
Storage of ECS imported objects.
Collection of ECS settings.
static getInstance()
Get singleton instance.
Stores relevant user data.
getFirstname()
get firstname
getLastname()
getLastname
getLogin()
get login
getImportId()
get Email
getEmail()
get email
getInstitution()
get institution
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
language handling
Class ilMailOptions this class handles user mails.
User class.
const PASSWD_CRYPTED
static _lookupId($a_user_str)
static _lookupExternalAccount(int $a_user_id)
static _lookupObjIdByImportId(string $import_id)
Get (latest) object id for an import id.
static _writeImportId(int $obj_id, string $import_id)
write import id to db (static)
Class ilRbacAdmin Core functions for role based access control.
static set(string $a_var, $a_val)
Set a value.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const SYSTEM_USER_ID
This file contains constants for PHPStan analyis, see: https://phpstan.org/config-reference#constants...
Definition: constants.php:26
const ANONYMOUS_USER_ID
Definition: constants.php:27
$server
global $DIC
Definition: feed.php:28
Interface of auth credentials.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$res
Definition: ltiservices.php:69
static http()
Fetches the global http state from ILIAS.
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
array $details
Details for error message relating to last request processed.
Definition: System.php:109