ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilAuthProviderECS.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
21use ILIAS\Refinery\Factory as Refinery;
22use ILIAS\HTTP\Services as HTTPServices;
23
30{
35 private Refinery $refinery;
36 private HTTPServices $http;
39
40 protected ?int $mid = null;
41 protected ?string $abreviation = null;
42
45
46
52 {
54
55 global $DIC;
56
57 $this->clientIniFile = $DIC->clientIni();
58 $this->rbacAdmin = $DIC->rbac()->admin();
59 $this->setting = $DIC->settings();
60 $this->lng = $DIC->language();
61 $this->lng->loadLanguageModule('ecs');
62 $this->http = $DIC->http();
63 $this->refinery = $DIC->refinery();
64 $this->authSession = $DIC['ilAuthSession'];
65 $this->ctrl = $DIC->ctrl();
66
67 $this->initECSServices();
68 }
69
73 public function getAbreviation(): string
74 {
75 return $this->abreviation;
76 }
77
81 public function getMID(): int
82 {
83 return $this->mid;
84 }
85
86 public function setMID(int $a_mid): void
87 {
88 $this->mid = $a_mid;
89 }
90
94 public function setCurrentServer(ilECSSetting $server): void
95 {
96 $this->currentServer = $server;
97 }
98
103 {
105 }
106
111 {
112 return $this->servers;
113 }
114
115
119 public function doAuthentication(\ilAuthStatus $status): bool
120 {
121 $this->getLogger()->debug('Starting ECS authentication');
122 if (!$this->getServerSettings()->activeServerExists()) {
123 $this->getLogger()->warning('No active ecs server found. Aborting');
124 $this->handleAuthenticationFail($status, 'err_wrong_login');
125 return false;
126 }
127
128 // Iterate through all active ecs instances
129 foreach ($this->getServerSettings()->getServers(ilECSServerSettings::ACTIVE_SERVER) as $server) {
130 $this->setCurrentServer($server);
131 if ($this->validateHash()) {
132 return $this->handleLoginByAuthMode($status);
133 }
134 }
135 $this->getLogger()->warning('Could not validate ecs hash for any active server.');
136 $this->handleAuthenticationFail($status, 'err_wrong_login');
137 return false;
138 }
139
144 protected function handleLoginByAuthMode(ilAuthStatus $status): bool
145 {
146 $is_external_account = false;
147 if ($this->http->wrapper()->query()->has('ecs_external_account')) {
148 $is_external_account = $this->http->wrapper()->query()->retrieve(
149 'ecs_external_account',
150 $this->refinery->kindlyTo()->bool()
151 );
152 }
153 $redirection_target = '';
154 if ($this->http->wrapper()->query()->has('target')) {
155 $redirection_target = $this->http->wrapper()->query()->retrieve(
156 'target',
157 $this->refinery->kindlyTo()->string()
158 );
159 }
160 $part_settings = new ilECSParticipantSetting(
161 $this->getCurrentServer()->getServerId(),
162 $this->getMID()
163 );
164 if ($this->resumeCurrentSession()) {
165 $this->getLogger()->debug('Continuing current user session');
167 $status->setAuthenticatedUserId($this->authSession->getUserId());
168 return true;
169 }
170 if (
171 $is_external_account &&
172 $part_settings->getIncomingAuthType() === ilECSParticipantSetting::INCOMING_AUTH_TYPE_LOGIN_PAGE
173 ) {
174 $this->getLogger()->info('ILIAS login page authentication required.');
175 ilSession::set('success', $this->lng->txt('ecs_login_success_ilias'));
177 $this->ctrl->redirectToURL('login.php?target=' . $redirection_target);
178 return false;
179 }
180 if (
181 $is_external_account &&
182 $part_settings->getIncomingAuthType() === ilECSParticipantSetting::INCOMING_AUTH_TYPE_SHIBBOLETH
183 ) {
184 $this->getLogger()->info('Redirect to shibboleth authentication');
186 $this->ctrl->redirectToURL('shib_login.php?target=' . $redirection_target);
187 }
188 if ($part_settings->areIncomingLocalAccountsSupported()) {
189 // handle successful authentication
190 $new_usr_id = $this->handleLogin();
191 $this->getLogger()->info('ECS authentication successful.');
193 $status->setAuthenticatedUserId($new_usr_id);
194 return true;
195 }
196 $this->handleAuthenticationFail($status, 'err_wrong_login');
197 return false;
198 }
199
200 protected function resumeCurrentSession(): bool
201 {
202 $session_user_id = $this->authSession->getUserId();
203 if (!$session_user_id || $session_user_id === ANONYMOUS_USER_ID) {
204 $this->getLogger()->debug('No valid session found');
205 $this->authSession->setAuthenticated(false, ANONYMOUS_USER_ID);
206 return false;
207 }
208 $session_ext_account = ilObjUser::_lookupExternalAccount($session_user_id);
209 $user = new ilECSUser($this->http->request()->getQueryParams());
210 $this->getLogger()->debug('ECS user name: ' . $user->getLogin());
211 $this->getLogger()->debug('Session external account: ' . $session_ext_account);
212 if (!$session_ext_account || strcmp($user->getLogin(), $session_ext_account) !== 0) {
213 $this->getLogger()->debug('No matching session found. Terminating current user session.');
214 $this->authSession->setAuthenticated(false, ANONYMOUS_USER_ID);
215 return false;
216 }
217 // assign to ECS global role
218 $this->rbacAdmin->assignUser($this->getCurrentServer()->getGlobalRole(), $this->authSession->getUserId());
219 return true;
220 }
221
222
226 public function handleLogin()
227 {
228 $user = new ilECSUser($this->http->request()->getQueryParams());
229
230 if (!$usr_id = ilObject::_lookupObjIdByImportId($user->getImportId())) {
231 $username = $this->createUser($user);
232 } else {
233 $username = $this->updateUser($user, $usr_id);
234 }
235
236 // set user imported
237 $import = new ilECSImport($this->getCurrentServer()->getServerId(), $usr_id);
238 $import->save();
239
240 // Store remote user data
241 $remoteUserRepository = new ilECSRemoteUserRepository();
242 $remoteUserRepository->createIfNotExisting(
243 $this->getCurrentServer()->getServerId(),
244 $this->getMID(),
245 ilObjUser::_lookupId($username),
246 $user->getImportId()
247 );
248
249 $this->getLogger()->info('Current user is: ' . $username);
250
251 return ilObjUser::_lookupId($username);
252 }
253
254 public function initRemoteUserWithRemoteId(): void
255 {
256 $user = new ilECSUser($this->http->request()->getQueryParams());
257
258 // Store remote user data
259 $remoteUserRepository = new ilECSRemoteUserRepository();
260 $remoteUserRepository->createIfRemoteUserNotExisting(
261 $this->getCurrentServer()->getServerId(),
262 $this->getMID(),
263 0,
264 $user->getLogin()
265 );
266 }
267
271 public function validateHash(): bool
272 {
273 // fetch hash
274 $hash = "";
275 if ($this->http->wrapper()->query()->has('ecs_hash')) {
276 $hash = $this->http->wrapper()->query()->retrieve(
277 'ecs_hash',
278 $this->refinery->kindlyTo()->string()
279 );
280 }
281 if ($this->http->wrapper()->query()->has('ecs_hash_url')) {
282 $hashurl = urldecode(
283 $this->http->wrapper()->query()->retrieve(
284 'ecs_hash_url',
285 $this->refinery->kindlyTo()->string()
286 )
287 );
288 $hash = basename(parse_url($hashurl, PHP_URL_PATH));
289 }
290
291 $this->getLogger()->info('Using ecs hash: ' . $hash);
292 // Check if hash is valid ...
293 try {
294 $connector = new ilECSConnector($this->getCurrentServer());
295 $res = $connector->getAuth($hash);
296 $auths = $res->getResult();
297
298 //$this->getLogger()->dump($auths, ilLogLevel::DEBUG);
299
300 if ($auths->pid) {
301 try {
302 $reader = ilECSCommunityReader::getInstanceByServerId($this->getCurrentServer()->getServerId());
303 foreach ($reader->getParticipantsByPid($auths->pid) as $participant) {
304 if ($participant->getOrganisation() instanceof \ilECSOrganisation) {
305 $this->abreviation = $participant->getOrganisation()->getAbbreviation();
306 break;
307 }
308 }
309 if (!$this->abreviation) {
310 $this->abreviation = $auths->abbr;
311 }
312 } catch (Exception $e) {
313 $this->getLogger()->warning('Authentication failed with message: ' . $e->getMessage());
314 return false;
315 }
316 } else {
317 $this->abreviation = $auths->abbr;
318 }
319
320 $this->getLogger()->debug('Got abbreviation: ' . $this->abreviation);
321 } catch (ilECSConnectorException $e) {
322 $this->getLogger()->warning('Authentication failed with message: ' . $e->getMessage());
323 return false;
324 }
325
326 // read current mid
327 try {
328 $connector = new ilECSConnector($this->getCurrentServer());
329 $details = $connector->getAuth($hash, true);
330
331 //$this->getLogger()->dump($details, ilLogLevel::DEBUG);
332 $this->getLogger()->debug('Token create for mid: ' . $details->getFirstSender());
333
334 $this->setMID($details->getFirstSender());
335 } catch (ilECSConnectorException $e) {
336 $this->getLogger()->warning('Receiving mid failed with message: ' . $e->getMessage());
337 return false;
338 }
339 return true;
340 }
341
342
346 private function initECSServices(): void
347 {
348 $this->servers = ilECSServerSettings::getInstance();
349 }
350
354 protected function createUser(ilECSUser $user): string
355 {
356 $userObj = new ilObjUser();
357 $userObj->setOwner(SYSTEM_USER_ID);
358
359 $local_user = ilAuthUtils::_generateLogin($this->getAbreviation() . '_' . $user->getLogin());
360
361 // system data
362 $userObj->setLogin($local_user);
363 $userObj->setFirstname($user->getFirstname());
364 $userObj->setLastname($user->getLastname());
365 $userObj->setTitle($userObj->getFullname());
366 $userObj->setDescription($userObj->getEmail());
367 $userObj->setEmail($user->getEmail());
368 $userObj->setInstitution($user->getInstitution());
369 $userObj->setPasswd('', ilObjUser::PASSWD_CRYPTED);
370 $userObj->setAuthMode('ecs');
371 // set user language to system language
372 $userObj->setLanguage($this->setting->get("language"));
373
374 // Time limit
375 $userObj->setTimeLimitUnlimited(false);
376 $userObj->setTimeLimitFrom(time() - 5);
377 $userObj->setTimeLimitUntil(time() + (int) $this->clientIniFile->readVariable("session", "expire"));
378
379 // Create user in DB
380 $userObj->setOwner(6);
381 $tmp_date = new ilDateTime(time(), IL_CAL_UNIX);
382 $userObj->setAgreeDate($tmp_date->get(IL_CAL_DATETIME));
383 $userObj->create();
384 $userObj->setActive(true);
385 $userObj->saveAsNew();
386 $userObj->updateOwner();
387 $userObj->writePrefs();
388
389 if ($this->getCurrentServer()->getGlobalRole()) {
390 $this->rbacAdmin->assignUser($this->getCurrentServer()->getGlobalRole(), $userObj->getId());
391 }
392 ilObject::_writeImportId($userObj->getId(), $user->getImportId());
393
394 $this->getLogger()->info('Created new remote user with usr_id: ' . $user->getImportId());
395
396 // Send Mail
397 #$this->sendNotification($userObj);
398 $this->resetMailOptions($userObj->getId());
399
400 return $userObj->getLogin();
401 }
402
406 protected function updateUser(ilECSUser $user, int $a_local_user_id): string
407 {
408 $user_obj = new ilObjUser($a_local_user_id);
409 $user_obj->setFirstname($user->getFirstname());
410 $user_obj->setLastname($user->getLastname());
411 $user_obj->setEmail($user->getEmail());
412 $user_obj->setInstitution($user->getInstitution());
413 $user_obj->setActive(true);
414
415 $until = $user_obj->getTimeLimitUntil();
416
417 if ($until < (time() + (int) $this->clientIniFile->readVariable('session', 'expire'))) {
418 $user_obj->setTimeLimitFrom(time() - 60);
419 $user_obj->setTimeLimitUntil(time() + (int) $this->clientIniFile->readVariable("session", "expire"));
420 }
421 $user_obj->refreshLogin();
422 $user_obj->update();
423
424 if ($this->getCurrentServer()->getGlobalRole()) {
425 $this->rbacAdmin->assignUser(
426 $this->getCurrentServer()->getGlobalRole(),
427 $user_obj->getId()
428 );
429 }
430
431 $this->resetMailOptions($a_local_user_id);
432
433 $this->getLogger()->debug('Finished update of remote user with usr_id: ' . $user->getImportId());
434 return $user_obj->getLogin();
435 }
436
441 protected function resetMailOptions(int $a_usr_id): void
442 {
443 $options = new ilMailOptions($a_usr_id);
444 $options->setIncomingType(ilMailOptions::INCOMING_LOCAL);
445 $options->updateOptions();
446 }
447}
Builds data types.
Definition: Factory.php:36
Class Services.
Definition: Services.php:38
const IL_CAL_UNIX
const IL_CAL_DATETIME
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.
handleAuthenticationFail(ilAuthStatus $status, string $a_reason)
ilAuthCredentials $credentials
setAuthenticatedUserId(int $a_id)
setStatus(int $a_status)
Set auth status.
const int STATUS_AUTHENTICATED
static _generateLogin(string $a_login)
generate free login by starting with a default string and adding postfix numbers
@classDescription Date and time handling
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
INIFile Parser Early access in init proceess! Avoid further dependencies like logging or other servic...
language handling
final const int INCOMING_LOCAL
User class.
const PASSWD_CRYPTED
static _lookupExternalAccount(int $a_user_id)
static _lookupId(string|array $a_user_str)
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.
ILIAS Setting Class.
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
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
global $DIC
Definition: shib_login.php:26
$server
Definition: shib_login.php:28