ILIAS  release_8 Revision v8.24
class.ilOpenIdConnectSettingsGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
28{
29 private const STAB_SETTINGS = 'settings';
30 private const STAB_PROFILE = 'profile';
31 private const STAB_ROLES = 'roles';
32
33 private const DEFAULT_CMD = 'settings';
34 private int $ref_id;
36 private $body;
39 private ilCtrl $ctrl;
47
48 public function __construct(int $a_ref_id)
49 {
50 global $DIC;
51
52 $this->ref_id = $a_ref_id;
53
54 $this->lng = $DIC->language();
55 $this->lng->loadLanguageModule('auth');
56
57 $this->mainTemplate = $DIC->ui()->mainTemplate();
58 $this->tabs = $DIC->tabs();
59 $this->ctrl = $DIC->ctrl();
60 $this->logger = $DIC->logger()->auth();
61
62 $this->access = $DIC->access();
63 $this->review = $DIC->rbac()->review();
64 $this->error = $DIC['ilErr'];
65 $this->upload = $DIC->upload();
66 $this->body = $DIC->http()->request()->getParsedBody();
68 }
69
70 protected function checkAccess(string $a_permission): void
71 {
72 if (!$this->checkAccessBool($a_permission)) {
73 $this->error->raiseError($this->lng->txt('msg_no_perm_read'), $this->error->WARNING);
74 }
75 }
76
77 protected function checkAccessBool(string $a_permission): bool
78 {
79 return $this->access->checkAccess($a_permission, '', $this->ref_id);
80 }
81
82 public function executeCommand(): void
83 {
84 $this->checkAccess('read');
85
86 switch ($this->ctrl->getNextClass()) {
87 default:
88 $cmd = $this->ctrl->getCmd(self::DEFAULT_CMD);
89 $this->$cmd();
90 break;
91 }
92 }
93
94 protected function settings(ilPropertyFormGUI $form = null): void
95 {
96 $this->checkAccess('read');
97 $this->setSubTabs(self::STAB_SETTINGS);
98
99
100 if (!$form instanceof ilPropertyFormGUI) {
101 $form = $this->initSettingsForm();
102 }
103
104 $this->mainTemplate->setContent($form->getHTML());
105 }
106
108 {
109 $form = new ilPropertyFormGUI();
110 $form->setTitle($this->lng->txt('auth_oidc_settings_title'));
111 $form->setFormAction($this->ctrl->getFormAction($this));
112
113 // activation
114 $activation = new ilCheckboxInputGUI(
115 $this->lng->txt('auth_oidc_settings_activation'),
116 'activation'
117 );
118 $activation->setChecked($this->settings->getActive());
119 $form->addItem($activation);
120
121 // provider
123 $this->lng->txt('auth_oidc_settings_provider'),
124 'provider'
125 );
126 $provider->setRequired(true);
127 $provider->setValue($this->settings->getProvider());
128 $form->addItem($provider);
129
131 $this->lng->txt('auth_oidc_settings_client_id'),
132 'client_id'
133 );
134 $client_id->setRequired(true);
135 $client_id->setValue($this->settings->getClientId());
136 $form->addItem($client_id);
137
138 // secret
140 $this->lng->txt('auth_oidc_settings_secret'),
141 'secret'
142 );
143 $secret->setSkipSyntaxCheck(true);
144 $secret->setRetype(false);
145 $secret->setRequired(false);
146 if ($this->settings->getSecret() !== '') {
147 $secret->setValue('******');
148 }
149 $form->addItem($secret);
150
151 $default_scope = new ilTextInputGUI(
152 $this->lng->txt('auth_oidc_settings_additional_scopes'),
153 "default_scope"
154 );
155 $default_scope->setValue(ilOpenIdConnectSettings::DEFAULT_SCOPE);
156 $default_scope->setDisabled(true);
157 $form->addItem($default_scope);
158
160 "",
161 "scopes"
162 );
163 $scopes->setMulti(true);
164 $scopeValues = $this->settings->getAdditionalScopes();
165 if (isset($scopeValues[0])) {
166 $scopes->setValue($scopeValues[0]);
167 }
168 $scopes->setMultiValues($scopeValues);
169 $form->addItem($scopes);
170
171
172 // validation options
173 $validation_options = new ilRadioGroupInputGUI(
174 $this->lng->txt('auth_oidc_settings_validate_scopes'),
175 'validate_scopes'
176 );
177 $validation_options->setValue((string) $this->settings->getValidateScopes());
178 $form->addItem($validation_options);
179
180 $base_valid_url_option = new ilRadioOption(
181 $this->lng->txt('auth_oidc_settings_validate_scope_default'),
183 );
184
185 $validation_options->addOption($base_valid_url_option);
186
187 $custom_validation_url = new ilTextInputGUI(
188 '',
189 'custom_discovery_url'
190 );
191
192 $custom_valid_url_option = new ilRadioOption(
193 $this->lng->txt('auth_oidc_settings_validate_scope_custom'),
195 );
196 $validation_options->addOption($custom_valid_url_option);
197 $custom_validation_url->setValue($this->settings->getCustomDiscoveryUrl() ?? '');
198 $custom_validation_url->setMaxLength(120);
199 $custom_validation_url->setInfo($this->lng->txt('auth_oidc_settings_discovery_url'));
200 $custom_valid_url_option->addSubItem($custom_validation_url);
201 $no_validation_option = new ilRadioOption(
202 $this->lng->txt('auth_oidc_settings_validate_scope_none'),
204 );
205 $validation_options->addOption($no_validation_option);
206
207 // login element
208 $login_element = new ilRadioGroupInputGUI(
209 $this->lng->txt('auth_oidc_settings_le'),
210 'le'
211 );
212 $login_element->setRequired(true);
213 $login_element->setValue((string) $this->settings->getLoginElementType());
214 $form->addItem($login_element);
215
216 // le -> type text
217 $text_option = new ilRadioOption(
218 $this->lng->txt('auth_oidc_settings_txt'),
220 );
221 $login_element->addOption($text_option);
222
223 // le -> type text -> text
224 $text = new ilTextInputGUI(
225 '',
226 'le_text'
227 );
228 $text->setValue($this->settings->getLoginElemenText());
229 $text->setMaxLength(120);
230 $text->setInfo($this->lng->txt('auth_oidc_settings_txt_val_info'));
231 $text_option->addSubItem($text);
232
233 // le -> type img
234 $img_option = new ilRadioOption(
235 $this->lng->txt('auth_oidc_settings_img'),
237 );
238 $login_element->addOption($img_option);
239
240 $image = new ilImageFileInputGUI(
241 '',
242 'le_img'
243 );
244 $image->setAllowDeletion(false);
245
246 if ($this->settings->hasImageFile()) {
247 $image->setImage($this->settings->getImageFilePath());
248 }
249 $image->setInfo($this->lng->txt('auth_oidc_settings_img_file_info'));
250 $img_option->addSubItem($image);
251
252 // login options
253 $login_options = new ilRadioGroupInputGUI(
254 $this->lng->txt('auth_oidc_settings_login_options'),
255 'login_prompt'
256 );
257 $login_options->setValue((string) $this->settings->getLoginPromptType());
258
259 // enforce login
260 $enforce = new ilRadioOption(
261 $this->lng->txt('auth_oidc_settings_login_option_enforce'),
263 );
264 $enforce->setInfo($this->lng->txt('auth_oidc_settings_login_option_enforce_info'));
265 $login_options->addOption($enforce);
266
267 // default login
268 $default = new ilRadioOption(
269 $this->lng->txt('auth_oidc_settings_login_option_default'),
271 );
272 $default->setInfo($this->lng->txt('auth_oidc_settings_login_option_default_info'));
273 $login_options->addOption($default);
274
275 $form->addItem($login_options);
276
277 // logout scope
278 $logout_scope = new ilRadioGroupInputGUI(
279 $this->lng->txt('auth_oidc_settings_logout_scope'),
280 'logout_scope'
281 );
282 $logout_scope->setValue((string) $this->settings->getLogoutScope());
283
284 // scope global
285 $global_scope = new ilRadioOption(
286 $this->lng->txt('auth_oidc_settings_logout_scope_global'),
288 );
289 $global_scope->setInfo($this->lng->txt('auth_oidc_settings_logout_scope_global_info'));
290 $logout_scope->addOption($global_scope);
291
292 // ilias scope
293 $ilias_scope = new ilRadioOption(
294 $this->lng->txt('auth_oidc_settings_logout_scope_local'),
296 );
297 $ilias_scope->setInfo($this->lng->txt('auth_oidc_settings_logout_scope_local_info'));
298 $logout_scope->addOption($ilias_scope);
299
300 $form->addItem($logout_scope);
301
302 $use_custom_session = new ilCheckboxInputGUI(
303 $this->lng->txt('auth_oidc_settings_custom_session_duration_type'),
304 'custom_session'
305 );
306 $use_custom_session->setOptionTitle(
307 $this->lng->txt('auth_oidc_settings_custom_session_duration_option')
308 );
309 $use_custom_session->setChecked($this->settings->isCustomSession());
310 $form->addItem($use_custom_session);
311
312 // session duration
314 $this->lng->txt('auth_oidc_settings_session_duration'),
315 'session_duration'
316 );
317 $session->setValue((string) $this->settings->getSessionDuration());
318 $session->setSuffix($this->lng->txt('minutes'));
319 $session->setMinValue(5);
320 $session->setMaxValue(1440);
321 $session->setRequired(true);
322 $use_custom_session->addSubItem($session);
323
324 if ($this->checkAccessBool('write')) {
325 // save button
326 $form->addCommandButton('saveSettings', $this->lng->txt('save'));
327 }
328
329 // User sync settings --------------------------------------------------------------
330 $user_sync = new ilFormSectionHeaderGUI();
331 $user_sync->setTitle($this->lng->txt('auth_oidc_settings_section_user_sync'));
332 $form->addItem($user_sync);
333
334 $sync = new ilCheckboxInputGUI(
335 $this->lng->txt('auth_oidc_settings_user_sync'),
336 'sync'
337 );
338 $sync->setChecked($this->settings->isSyncAllowed());
339 $sync->setInfo($this->lng->txt('auth_oidc_settings_user_sync_info'));
340 $sync->setValue("1");
341 $form->addItem($sync);
342
343 $roles = new ilSelectInputGUI(
344 $this->lng->txt('auth_oidc_settings_default_role'),
345 'role'
346 );
347 $roles->setValue($this->settings->getRole());
348 $roles->setInfo($this->lng->txt('auth_oidc_settings_default_role_info'));
349 $roles->setOptions($this->prepareRoleSelection());
350 $roles->setRequired(true);
351 $sync->addSubItem($roles);
352
353 $user_attr = new ilTextInputGUI(
354 $this->lng->txt('auth_oidc_settings_user_attr'),
355 'username'
356 );
357 $user_attr->setValue($this->settings->getUidField());
358 $user_attr->setRequired(true);
359 $form->addItem($user_attr);
360
361 return $form;
362 }
363
364 protected function saveSettings(): void
365 {
366 $this->checkAccess('write');
367
368 $form = $this->initSettingsForm();
369 if (!$form->checkInput()) {
370 $this->mainTemplate->setOnScreenMessage('failure', $this->lng->txt('err_check_input'));
371 $form->setValuesByPost();
372 $this->settings($form);
373 return;
374 }
375
376 $scopes = [];
377 if (!empty($form->getInput('scopes'))) {
378 $scopes = $form->getInput('scopes');
379 foreach ($scopes as $key => $value) {
380 if (empty($value)) {
381 array_splice($scopes, $key, 1);
382 }
383 }
384 }
385
386 try {
387 switch ((int) $form->getInput('validate_scopes')) {
389 $discoveryURL = $form->getInput('provider') . '/.well-known/openid-configuration';
390 break;
392 $discoveryURL = $form->getInput('custom_discovery_url');
393 break;
394 default:
395 $discoveryURL = null;
396 break;
397 }
398 $validation_result = !is_null($discoveryURL) ? $this->settings->validateScopes($discoveryURL, (array) $scopes) : [];
399
400 if (!empty($validation_result)) {
401 if (ilOpenIdConnectSettings::VALIDATION_ISSUE_INVALID_SCOPE === $validation_result[0]) {
402 $this->mainTemplate->setOnScreenMessage(
403 'failure',
404 sprintf($this->lng->txt('auth_oidc_settings_invalid_scopes'), implode(",", $validation_result[1]))
405 );
406 } else {
407 $this->mainTemplate->setOnScreenMessage(
408 'failure',
409 sprintf($this->lng->txt('auth_oidc_settings_discovery_error'), $validation_result[1])
410 );
411 }
412 $form->setValuesByPost();
413 $this->settings($form);
414 return;
415 }
416 } catch (ilCurlConnectionException $e) {
417 $this->mainTemplate->setOnScreenMessage(
418 'failure',
419 $e->getMessage()
420 );
421 $form->setValuesByPost();
422 $this->settings($form);
423 return;
424 }
425
426 $this->settings->setActive((bool) $form->getInput('activation'));
427 $this->settings->setProvider((string) $form->getInput('provider'));
428 $this->settings->setClientId((string) $form->getInput('client_id'));
429 if ((string) $form->getInput('secret') !== '' && strcmp($form->getInput('secret'), '******') !== 0) {
430 $this->settings->setSecret((string) $form->getInput('secret'));
431 }
432 $this->settings->setAdditionalScopes((array) $scopes);
433 $this->settings->setLoginElementType((int) $form->getInput('le'));
434 $this->settings->setLoginElementText((string) $form->getInput('le_text'));
435 $this->settings->setLoginPromptType((int) $form->getInput('login_prompt'));
436 $this->settings->setLogoutScope((int) $form->getInput('logout_scope'));
437 $this->settings->useCustomSession((bool) $form->getInput('custom_session'));
438 $this->settings->setSessionDuration((int) $form->getInput('session_duration'));
439 $this->settings->allowSync((bool) $form->getInput('sync'));
440 $this->settings->setRole((int) $form->getInput('role'));
441 $this->settings->setUidField((string) $form->getInput('username'));
442
443 $fileData = (array) $form->getInput('le_img');
444
445 if ((string) ($fileData['tmp_name'] ?? '') !== '') {
447 }
448
449 $this->settings->setValidateScopes((int) $form->getInput('validate_scopes'));
450 if (ilOpenIdConnectSettings::URL_VALIDATION_CUSTOM === $this->settings->getValidateScopes()) {
451 $this->settings->setCustomDiscoveryUrl($form->getInput('custom_discovery_url'));
452 }
453 $this->settings->save();
454
455 $this->mainTemplate->setOnScreenMessage('success', $this->lng->txt('settings_saved'), true);
456 $this->ctrl->redirect($this, 'settings');
457 }
458
459 protected function saveImageFromHttpRequest(): void
460 {
461 try {
462 if (!$this->upload->hasBeenProcessed()) {
463 $this->upload->process();
464 }
465 foreach ($this->upload->getResults() as $single_file_upload) {
466 if ($single_file_upload->isOK()) {
467 $this->settings->deleteImageFile();
468 $this->upload->moveFilesTo(
470 \ILIAS\FileUpload\Location::WEB
471 );
472 $this->settings->setLoginElementImage($single_file_upload->getName());
473 }
474 }
475 } catch (\ILIAS\Filesystem\Exception\IllegalStateException $e) {
476 $this->logger->warning('Upload failed with message: ' . $e->getMessage());
477 }
478 }
479
484 protected function prepareRoleSelection(bool $a_with_select_option = true): array
485 {
486 $global_roles = ilUtil::_sortIds(
487 $this->review->getGlobalRoles(),
488 'object_data',
489 'title',
490 'obj_id'
491 );
492
493 $select = [];
494 if ($a_with_select_option) {
495 $select[0] = $this->lng->txt('links_select_one');
496 }
497 foreach ($global_roles as $role_id) {
498 if ($role_id === ANONYMOUS_ROLE_ID) {
499 continue;
500 }
501 $select[(string) $role_id] = ilObject::_lookupTitle((int) $role_id);
502 }
503
504 return $select;
505 }
506
507 protected function profile(ilPropertyFormGUI $form = null): void
508 {
509 $this->checkAccess('read');
510 $this->setSubTabs(self::STAB_PROFILE);
511
512 if (!$form instanceof ilPropertyFormGUI) {
513 $form = $this->initProfileForm();
514 }
515 $this->mainTemplate->setContent($form->getHTML());
516 }
517
518 protected function initProfileForm(): ilPropertyFormGUI
519 {
520 $form = new ilPropertyFormGUI();
521 $form->setTitle($this->lng->txt('auth_oidc_mapping_table'));
522 $form->setFormAction($this->ctrl->getFormAction($this, 'saveProfile'));
523
524 foreach ($this->settings->getProfileMappingFields() as $field => $lng_key) {
525 $text_form = new ilTextInputGUI($this->lng->txt($lng_key));
526 $text_form->setPostVar($field . "_value");
527 $text_form->setValue($this->settings->getProfileMappingFieldValue($field));
528 $form->addItem($text_form);
529
530 $checkbox_form = new ilCheckboxInputGUI('');
531 $checkbox_form->setValue("1");
532 $checkbox_form->setPostVar($field . "_update");
533 $checkbox_form->setChecked($this->settings->getProfileMappingFieldUpdate($field));
534 $checkbox_form->setOptionTitle($this->lng->txt('auth_oidc_update_field_info'));
535 $form->addItem($checkbox_form);
536 }
537
538 if ($this->checkAccessBool('write')) {
539 $form->addCommandButton('saveProfile', $this->lng->txt('save'));
540 }
541
542 return $form;
543 }
544
545 protected function saveProfile(): void
546 {
547 $this->checkAccessBool('write');
548
549 $form = $this->initProfileForm();
550 if (!$form->checkInput()) {
551 $this->mainTemplate->setOnScreenMessage('failure', $this->lng->txt('err_check_input'));
552 $form->setValuesByPost();
553 $this->profile($form);
554 return;
555 }
556
557 foreach ($this->settings->getProfileMappingFields() as $field => $lng_key) {
558 $this->settings->setProfileMappingFieldValue(
559 $field,
560 $form->getInput($field . '_value')
561 );
562 $this->settings->setProfileMappingFieldUpdate(
563 $field,
564 (bool) $form->getInput($field . '_update')
565 );
566 }
567 $this->settings->save();
568 $this->mainTemplate->setOnScreenMessage('success', $this->lng->txt('settings_saved'), true);
569 $this->ctrl->redirect($this, self::STAB_PROFILE);
570 }
571
572 protected function roles(ilPropertyFormGUI $form = null): void
573 {
574 $this->checkAccess('read');
575 $this->setSubTabs(self::STAB_ROLES);
576
577 if (!$form instanceof ilPropertyFormGUI) {
578 $form = $this->initRolesForm();
579 }
580 $this->mainTemplate->setContent($form->getHTML());
581 }
582
583 protected function initRolesForm(): ilPropertyFormGUI
584 {
585 $form = new ilPropertyFormGUI();
586 $form->setTitle($this->lng->txt('auth_oidc_role_mapping_table'));
587 $form->setFormAction($this->ctrl->getFormAction($this, self::STAB_ROLES));
588
589 foreach ($this->prepareRoleSelection(false) as $role_id => $role_title) {
590 $role_map = new ilTextInputGUI(
591 $role_title,
592 'role_map_' . $role_id
593 );
594 $role_map->setInfo($this->lng->txt('auth_oidc_role_info'));
595 $role_map->setValue($this->settings->getRoleMappingValueForId((int) $role_id));
596 $form->addItem($role_map);
597
599 '',
600 'role_map_update_' . $role_id
601 );
602 $update->setOptionTitle($this->lng->txt('auth_oidc_update_role_info'));
603 $update->setValue("1");
604 $update->setChecked(!$this->settings->getRoleMappingUpdateForId((int) $role_id));
605 $form->addItem($update);
606 }
607
608 if ($this->checkAccessBool('write')) {
609 $form->addCommandButton('saveRoles', $this->lng->txt('save'));
610 }
611 return $form;
612 }
613
614 protected function saveRoles(): void
615 {
616 $this->checkAccess('write');
617 $form = $this->initRolesForm();
618 if ($form->checkInput()) {
619 $this->logger->dump($this->body, ilLogLevel::DEBUG);
620
621
622 $role_settings = [];
623 $role_valid = true;
624 foreach ($this->prepareRoleSelection(false) as $role_id => $role_title) {
625 $role_settings[(int) $role_id]['update'] = !$form->getInput('role_map_update_' . $role_id);
626 $role_settings[(int) $role_id]['value'] = '';
627
628 $input_role = trim($form->getInput('role_map_' . $role_id));
629 if ($input_role === '') {
630 continue;
631 }
632
633 $role_params = explode('::', $input_role);
634 $this->logger->dump($role_params, ilLogLevel::DEBUG);
635
636 if (count($role_params) !== 2) {
637 if ($form->getItemByPostVar('role_map_' . $role_id)) {
638 $form->getItemByPostVar('role_map_' . $role_id)->setAlert($this->lng->txt('msg_wrong_format'));
639 }
640 $role_valid = false;
641 continue;
642 }
643 $role_settings[(int) $role_id]['value'] = $input_role;
644 }
645
646 if (!$role_valid) {
647 $form->setValuesByPost();
648 $this->mainTemplate->setOnScreenMessage('failure', $this->lng->txt('err_check_input'));
649 $this->roles($form);
650 return;
651 }
652
653 $this->settings->setRoleMappings($role_settings);
654 $this->settings->save();
655 $this->mainTemplate->setOnScreenMessage('success', $this->lng->txt('settings_saved'), true);
656 $this->ctrl->redirect($this, 'roles');
657 }
658
659 $form->setValuesByPost();
660 $this->mainTemplate->setOnScreenMessage('failure', $this->lng->txt('err_check_input'));
661 $this->roles($form);
662 }
663
664 protected function setSubTabs(string $active_tab): void
665 {
666 $this->tabs->addSubTab(
667 self::STAB_SETTINGS,
668 $this->lng->txt('auth_oidc_' . self::STAB_SETTINGS),
669 $this->ctrl->getLinkTarget($this, self::STAB_SETTINGS)
670 );
671 $this->tabs->addSubTab(
672 self::STAB_PROFILE,
673 $this->lng->txt('auth_oidc_' . self::STAB_PROFILE),
674 $this->ctrl->getLinkTarget($this, self::STAB_PROFILE)
675 );
676 $this->tabs->addSubTab(
677 self::STAB_ROLES,
678 $this->lng->txt('auth_oidc_' . self::STAB_ROLES),
679 $this->ctrl->getLinkTarget($this, self::STAB_ROLES)
680 );
681
682 $this->tabs->activateSubTab($active_tab);
683 }
684}
error(string $a_errmsg)
This class represents a checkbox property in a property form.
Class ilCtrl provides processing control methods.
Error Handling & global info handling uses PEAR error class.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
language handling
Component logger with individual log levels by component id.
This class represents a number property in a property form.
static _lookupTitle(int $obj_id)
Class ilOpenIdConnectSettingsGUI.
settings(ilPropertyFormGUI $form=null)
prepareRoleSelection(bool $a_with_select_option=true)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents a property form user interface.
This class represents a property in a property form.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
class ilRbacReview Contains Review functions of core Rbac.
This class represents a selection list property in a property form.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents a text property in a property form.
static _sortIds(array $a_ids, string $a_table, string $a_field, string $a_id_name)
Function that sorts ids by a given table field using WHERE IN E.g: __sort(array(6,...
const ANONYMOUS_ROLE_ID
Definition: constants.php:28
global $DIC
Definition: feed.php:28
$update
Definition: imgupload.php:92
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$client_id
Definition: ltiauth.php:68
$scopes
Definition: ltitoken.php:99
$provider
Definition: ltitoken.php:83
Class FlySystemFileAccessTest \Provider\FlySystem @runTestsInSeparateProcesses @preserveGlobalState d...
string $key
Consumer key/client ID value.
Definition: System.php:193
string $secret
Shared secret.
Definition: System.php:43
Class ChatMainBarProvider \MainMenu\Provider.
$session