ILIAS  trunk Revision v11.0_alpha-1753-gb21ca8c4367
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
class.ilAuthUtils.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
27 {
28  public const LOCAL_PWV_FULL = 1;
29  public const LOCAL_PWV_NO = 2;
30  public const LOCAL_PWV_USER = 3;
31 
32 
33  public const AUTH_LOCAL = 1;
34  public const AUTH_LDAP = 2;
35  public const AUTH_SCRIPT = 4;
36  public const AUTH_SHIBBOLETH = 5;
37  public const AUTH_CAS = 6;
38  public const AUTH_SOAP = 7;
39  public const AUTH_HTTP = 8; // Used for WebDAV
40  public const AUTH_ECS = 9;
41 
42  public const AUTH_APACHE = 11;
43  public const AUTH_SAML = 12;
44 
45  public const AUTH_OPENID_CONNECT = 15;
46 
47  //TODO this is not used anywhere, can it be removed
48  private const AUTH_INACTIVE = 18;
49 
50  //TODO this is not used anywhere, can it be removed
51  private const AUTH_MULTIPLE = 20;
52 
53  //TODO this is not used anywhere, can it be removed
54  private const AUTH_SESSION = 21;
55 
56  public const AUTH_PROVIDER_LTI = 22;
57 
58  //TODO this is not used anywhere, can it be removed
59  private const AUTH_SOAP_NO_ILIAS_USER = -100;
60  //TODO this is not used anywhere, can it be removed
61  private const AUTH_LDAP_NO_ILIAS_USER = -200;
62 
63  // apache auhtentication failed...
64  // maybe no (valid) certificate or
65  // username could not be extracted
66  //TODO this is not used anywhere, can it be removed
67  private const AUTH_APACHE_FAILED = -500;
68 
69  //TODO this is not used anywhere, can it be removed
70  private const AUTH_SAML_FAILED = -501;
71 
72  //TODO this is not used anywhere, can it be removed
73  private const AUTH_MODE_INACTIVE = -1000;
74 
75  // an external user cannot be found in ilias, but his email address
76  // matches one or more ILIAS users
77  //TODO this is not used anywhere, can it be removed?
78  private const AUTH_SOAP_NO_ILIAS_USER_BUT_EMAIL = -101;
79  //TODO this is not used anywhere, can it be removed?
80  private const AUTH_CAS_NO_ILIAS_USER = -90;
81 
82  // ilUser validation (no login)
83  //TODO All these are is not used anywhere, can it be removed?
84  private const AUTH_USER_WRONG_IP = -600;
85  private const AUTH_USER_INACTIVE = -601;
86  private const AUTH_USER_TIME_LIMIT_EXCEEDED = -602;
87  private const AUTH_USER_SIMULTANEOUS_LOGIN = -603;
88 
90  public const REGEX_DELIMITERS = ['/', '~', '@', ';', '%', '`', '#'];
91 
95  public static function isAuthenticationForced(): bool
96  {
97  //TODO rework forced authentication concept
98  global $DIC;
99  $query_wrapper = $DIC->http()->wrapper()->query();
100  return $query_wrapper->has('ecs_hash') || $query_wrapper->has('ecs_hash_url');
101  }
102 
103  public static function handleForcedAuthentication(): void
104  {
105  global $DIC;
106  $query_wrapper = $DIC->http()->wrapper()->query();
107  $string_refinery = $DIC->refinery()->kindlyTo()->string();
108  if ($query_wrapper->has('ecs_hash') || $query_wrapper->has('ecs_hash_url')) {
109  $credentials = new ilAuthFrontendCredentials();
110  $credentials->setUsername($query_wrapper->retrieve('ecs_login', $string_refinery));
111  $credentials->setAuthMode((string) self::AUTH_ECS);
112 
113  $provider_factory = new ilAuthProviderFactory();
114  $providers = $provider_factory->getProviders($credentials);
115 
116  $status = ilAuthStatus::getInstance();
117 
118  $frontend_factory = new ilAuthFrontendFactory();
119  $frontend_factory->setContext(ilAuthFrontendFactory::CONTEXT_STANDARD_FORM);
120  $frontend = $frontend_factory->getFrontend(
121  $GLOBALS['DIC']['ilAuthSession'],
122  $status,
123  $credentials,
124  $providers
125  );
126 
127  $frontend->authenticate();
128 
129  switch ($status->getStatus()) {
131  return;
132 
135  return;
136  }
137  }
138  }
139 
143  public static function _getAuthMode(?string $a_auth_mode)
144  {
145  global $DIC;
146 
147  $ilSetting = $DIC['ilSetting'];
148 
149  if (null === $a_auth_mode) {
150  return $ilSetting->get("auth_mode");
151  }
152 
153  if (strpos($a_auth_mode, '_') !== false) {
154  $auth_arr = explode('_', $a_auth_mode);
155  $auth_switch = $auth_arr[0];
156  } else {
157  $auth_switch = $a_auth_mode;
158  }
159  switch ($auth_switch) {
160  case "local":
161  return self::AUTH_LOCAL;
162  break;
163 
164  case "ldap":
165  return ilLDAPServer::getKeyByAuthMode($a_auth_mode);
166 
167  case 'lti':
168  return ilAuthProviderLTI::getKeyByAuthMode($a_auth_mode);
169 
170  case "script":
171  return self::AUTH_SCRIPT;
172  break;
173 
174  case "shibboleth":
175  return self::AUTH_SHIBBOLETH;
176  break;
177 
178  case 'oidc':
179  return self::AUTH_OPENID_CONNECT;
180  break;
181 
182  case 'saml':
183  return ilSamlIdp::getKeyByAuthMode($a_auth_mode);
184 
185  case "cas":
186  return self::AUTH_CAS;
187  break;
188 
189  case "soap":
190  return self::AUTH_SOAP;
191  break;
192 
193  case 'ecs':
194  return self::AUTH_ECS;
195 
196  case 'apache':
197  return self::AUTH_APACHE;
198 
199  default:
200  return $ilSetting->get("auth_mode");
201  break;
202  }
203  }
204 
208  public static function _getAuthModeName($a_auth_key): string
209  {
210  switch ((int) $a_auth_key) {
211  case self::AUTH_LOCAL:
212  return "local";
213  break;
214 
215  case self::AUTH_LDAP:
216  // begin-patch ldap_multiple
217  return ilLDAPServer::getAuthModeByKey($a_auth_key);
218  // end-patch ldap_multiple
219 
220  case self::AUTH_PROVIDER_LTI:
221  return ilAuthProviderLTI::getAuthModeByKey($a_auth_key);
222 
223  case self::AUTH_CAS:
224  return "cas";
225  break;
226 
227  case self::AUTH_SCRIPT:
228  return "script";
229  break;
230 
231  case self::AUTH_SHIBBOLETH:
232  return "shibboleth";
233  break;
234 
235  case self::AUTH_SAML:
236  return ilSamlIdp::getAuthModeByKey($a_auth_key);
237 
238  case self::AUTH_SOAP:
239  return "soap";
240  break;
241 
242  case self::AUTH_ECS:
243  return 'ecs';
244 
245  case self::AUTH_APACHE:
246  return 'apache';
247 
248  case self::AUTH_OPENID_CONNECT:
249  return 'oidc';
250  break;
251 
252  default:
253  return "default";
254  break;
255  }
256  }
257 
261  public static function _getActiveAuthModes(): array
262  {
263  global $DIC;
264 
265  $ilSetting = $DIC['ilSetting'];
266 
267  $modes = [
268  'default' => $ilSetting->get("auth_mode"),
269  'local' => self::AUTH_LOCAL
270  ];
271 
272  foreach (ilLDAPServer::_getActiveServerList() as $sid) {
273  $modes['ldap_' . $sid] = (self::AUTH_LDAP . '_' . $sid);
274  }
275 
276  foreach (ilAuthProviderLTI::getAuthModes() as $sid) {
277  $modes['lti_' . $sid] = (self::AUTH_PROVIDER_LTI . '_' . $sid);
278  }
279 
280  if (ilOpenIdConnectSettings::getInstance()->getActive()) {
281  $modes['oidc'] = self::AUTH_OPENID_CONNECT;
282  }
283 
284  if ($ilSetting->get("shib_active")) {
285  $modes['shibboleth'] = self::AUTH_SHIBBOLETH;
286  }
287  if ($ilSetting->get("script_active")) {
288  $modes['script'] = self::AUTH_SCRIPT;
289  }
290  if ($ilSetting->get("cas_active")) {
291  $modes['cas'] = self::AUTH_CAS;
292  }
293  if ($ilSetting->get("soap_auth_active")) {
294  $modes['soap'] = self::AUTH_SOAP;
295  }
296  if ($ilSetting->get("apache_active")) {
297  $modes['apache'] = self::AUTH_APACHE;
298  }
299 
300  if (ilECSServerSettings::getInstance()->activeServerExists()) {
301  $modes['ecs'] = self::AUTH_ECS;
302  }
303 
304  foreach (ilSamlIdp::getActiveIdpList() as $idp) {
305  $idpId = $idp->getIdpId();
306  $modes['saml_' . $idpId] = self::AUTH_SAML . '_' . $idpId;
307  }
308 
309  // begin-path auth_plugin
310  foreach (self::getAuthPlugins() as $pl) {
311  foreach ($pl->getAuthIds() as $auth_id) {
312  if ($pl->isAuthActive($auth_id)) {
313  $modes[$pl->getAuthName($auth_id)] = $auth_id;
314  }
315  }
316  }
317  // end-path auth_plugin
318  return $modes;
319  }
320 
324  public static function _getAllAuthModes(): array
325  {
326  $modes = array(
327  self::AUTH_LOCAL,
328  self::AUTH_LDAP,
329  self::AUTH_SHIBBOLETH,
330  self::AUTH_SAML,
331  self::AUTH_CAS,
332  self::AUTH_SOAP,
333  self::AUTH_ECS,
334  self::AUTH_PROVIDER_LTI,
335  self::AUTH_OPENID_CONNECT,
336  self::AUTH_APACHE
337  );
338  $ret = array();
339  foreach ($modes as $mode) {
340  if ($mode === self::AUTH_PROVIDER_LTI) {
341  foreach (ilAuthProviderLTI::getAuthModes() as $sid) {
342  $id = self::AUTH_PROVIDER_LTI . '_' . $sid;
343  $ret[$id] = self::_getAuthModeName($id);
344  }
345  continue;
346  }
347 
348  // multi ldap implementation
349  if ($mode === self::AUTH_LDAP) {
350  foreach (ilLDAPServer::_getServerList() as $ldap_id) {
351  $id = self::AUTH_LDAP . '_' . $ldap_id;
352  $ret[$id] = self::_getAuthModeName($id);
353  }
354  continue;
355  }
356 
357  if ($mode === self::AUTH_SAML) {
358  foreach (ilSamlIdp::getAllIdps() as $idp) {
359  $id = self::AUTH_SAML . '_' . $idp->getIdpId();
360  $ret[$id] = self::_getAuthModeName($id);
361  }
362  continue;
363  }
364  $ret[$mode] = self::_getAuthModeName($mode);
365  }
366  return $ret;
367  }
368 
373  public static function _generateLogin(string $a_login): string
374  {
375  global $DIC;
376 
377  $ilDB = $DIC['ilDB'];
378 
379  // Check if username already exists
380  $found = false;
381  $postfix = 0;
382  $c_login = $a_login;
383  while (!$found) {
384  $r = $ilDB->query("SELECT login FROM usr_data WHERE login = " .
385  $ilDB->quote($c_login));
386  if ($r->numRows() > 0) {
387  $postfix++;
388  $c_login = $a_login . $postfix;
389  } else {
390  $found = true;
391  }
392  }
393 
394  return $c_login;
395  }
396 
397  public static function _hasMultipleAuthenticationMethods(): bool
398  {
399  if (count(ilLDAPServer::_getActiveServerList())) {
400  return true;
401  }
402 
403  global $DIC;
404 
405  $ilSetting = $DIC['ilSetting'];
406 
407  if ($ilSetting->get('apache_active')) {
408  return true;
409  }
410 
411  // begin-patch auth_plugin
412  foreach (self::getAuthPlugins() as $pl) {
413  foreach ($pl->getAuthIds() as $auth_id) {
414  if ($pl->getMultipleAuthModeOptions($auth_id)) {
415  return true;
416  }
417  }
418  }
419  // end-patch auth_plugin
420 
421 
422  return false;
423  }
424 
429  public static function _getMultipleAuthModeOptions(ilLanguage $lng): array
430  {
431  global $DIC;
432 
433  $ilSetting = $DIC['ilSetting'];
434  $options = [];
435  // in the moment only ldap is activated as additional authentication method
436 
437  $options[self::AUTH_LOCAL]['txt'] = $lng->txt('authenticate_ilias');
438 
439 
440  foreach (ilLDAPServer::_getActiveServerList() as $sid) {
442  $options[self::AUTH_LDAP . '_' . $sid]['txt'] = $server->getName();
443  }
444 
445  if ($ilSetting->get('apache_active')) {
446  global $DIC;
447 
448  $lng = $DIC['lng'];
449  $apache_settings = new ilSetting('apache_auth');
450  $options[self::AUTH_APACHE]['txt'] = $apache_settings->get('name', $lng->txt('apache_auth'));
451  $options[self::AUTH_APACHE]['hide_in_ui'] = true;
452  }
453 
454  if ($ilSetting->get('auth_mode', (string) self::AUTH_LOCAL) === (string) self::AUTH_LDAP) {
455  $default = self::AUTH_LDAP;
456  } else {
457  $default = self::AUTH_LOCAL;
458  }
459 
460  $default = $ilSetting->get('default_auth_mode', (string) $default);
461 
462  // begin-patch auth_plugin
463  $pls = self::getAuthPlugins();
464  foreach ($pls as $pl) {
465  $auths = $pl->getAuthIds();
466  foreach ($auths as $auth_id) {
467  $pl_auth_option = $pl->getMultipleAuthModeOptions($auth_id);
468  if ($pl_auth_option) {
469  $options += $pl_auth_option;
470  }
471  }
472  }
473  // end-patch auth_plugins
474 
475  if (array_key_exists($default, $options)) {
476  $options[$default]['checked'] = true;
477  }
478 
479  return $options;
480  }
481 
486  public static function _isExternalAccountEnabled(): bool
487  {
488  global $DIC;
489 
490  $ilSetting = $DIC['ilSetting'];
491 
492  if ($ilSetting->get("cas_active")) {
493  return true;
494  }
495  if ($ilSetting->get("soap_auth_active")) {
496  return true;
497  }
498  if ($ilSetting->get("shib_active")) {
499  return true;
500  }
501  if (count(ilLDAPServer::_getActiveServerList())) {
502  return true;
503  }
504 
506  return true;
507  }
508 
509  if (count(ilSamlIdp::getActiveIdpList()) > 0) {
510  return true;
511  }
512 
513  if (ilOpenIdConnectSettings::getInstance()->getActive()) {
514  return true;
515  }
516 
517  // begin-path auth_plugin
518  foreach (self::getAuthPlugins() as $pl) {
519  foreach ($pl->getAuthIds() as $auth_id) {
520  if ($pl->isAuthActive($auth_id) && $pl->isExternalAccountNameRequired($auth_id)) {
521  return true;
522  }
523  }
524  }
525  // end-path auth_plugin
526 
527  return false;
528  }
529 
534  public static function _allowPasswordModificationByAuthMode($a_auth_mode): bool
535  {
536  switch ((int) $a_auth_mode) {
537  case self::AUTH_LDAP:
538  case self::AUTH_ECS:
539  case self::AUTH_PROVIDER_LTI:
540  case self::AUTH_OPENID_CONNECT:
541  return false;
542  default:
543  return true;
544  }
545  }
546 
552  public static function _needsExternalAccountByAuthMode($a_auth_mode): bool
553  {
554  switch ($a_auth_mode) {
555  case self::AUTH_LOCAL:
556  case self::AUTH_APACHE:
557  return false;
558  default:
559  return true;
560  }
561  }
562 
566  public static function isPasswordModificationHidden(): bool
567  {
569  global $DIC;
570 
571  $ilSetting = $DIC['ilSetting'];
572 
573  return $ilSetting->get('usr_settings_hide_password') || $ilSetting->get('usr_settings_disable_password');
574  }
575 
581  public static function isLocalPasswordEnabledForAuthMode($a_authmode): bool
582  {
583  global $DIC;
584 
585  $ilSetting = $DIC->settings();
586 
587  switch ((int) $a_authmode) {
588  // always enabled
589  case self::AUTH_LOCAL:
590  case self::AUTH_APACHE:
591  return true;
592 
593  // No local passwords for these auth modes
594  case self::AUTH_LDAP:
595  case self::AUTH_ECS:
596  case self::AUTH_SCRIPT:
597  case self::AUTH_PROVIDER_LTI:
598  case self::AUTH_OPENID_CONNECT:
599  return false;
600 
601  case self::AUTH_SAML:
602  $idp = ilSamlIdp::getInstanceByIdpId(ilSamlIdp::getIdpIdByAuthMode((string) $a_authmode));
603  return $idp->isActive() && $idp->allowLocalAuthentication();
604 
605  case self::AUTH_SHIBBOLETH:
606  return (bool) $ilSetting->get("shib_auth_allow_local", '0');
607  case self::AUTH_SOAP:
608  return (bool) $ilSetting->get("soap_auth_allow_local", '0');
609  case self::AUTH_CAS:
610  return (bool) $ilSetting->get("cas_allow_local", '0');
611  }
612  return false;
613  }
614 
615 
621  public static function isPasswordModificationEnabled($a_authmode): bool
622  {
623  if (self::isPasswordModificationHidden()) {
624  return false;
625  }
626 
627  return self::isLocalPasswordEnabledForAuthMode($a_authmode);
628  }
629 
635  public static function supportsLocalPasswordValidation($a_authmode): int
636  {
637  switch ((int) $a_authmode) {
638  case self::AUTH_LDAP:
639  case self::AUTH_LOCAL:
640  return self::LOCAL_PWV_FULL;
641 
642  case self::AUTH_SHIBBOLETH:
643  case self::AUTH_OPENID_CONNECT:
644  case self::AUTH_SAML:
645  case self::AUTH_SOAP:
646  case self::AUTH_CAS:
647  if (!self::isPasswordModificationEnabled($a_authmode)) {
648  return self::LOCAL_PWV_NO;
649  }
650  return self::LOCAL_PWV_USER;
651 
652  case self::AUTH_PROVIDER_LTI:
653  case self::AUTH_ECS:
654  case self::AUTH_SCRIPT:
655  case self::AUTH_APACHE:
656  default:
657  return self::LOCAL_PWV_USER;
658  }
659  }
660 
664  public static function getAuthPlugins(): \Iterator
665  {
666  return $GLOBALS['DIC']['component.factory']->getActivePluginsInSlot('authhk');
667  }
668 
669  public static function getAuthModeTranslation(string $a_auth_key, string $auth_name = ''): ?string
670  {
671  global $DIC;
672 
673  $lng = $DIC['lng'];
674 
675  //TODO fix casting strings like 2_1 (auth_key for first ldap server) to int to get it to 2
676  switch ((int) $a_auth_key) {
677  case self::AUTH_LDAP:
678  $sid = ilLDAPServer::getServerIdByAuthMode($a_auth_key);
679  return ilLDAPServer::getInstanceByServerId($sid)->getName();
680 
681  case self::AUTH_PROVIDER_LTI:
682  $sid = ilAuthProviderLTI::getServerIdByAuthMode($a_auth_key);
684 
685 
686  case self::AUTH_SAML:
687  $idp_id = ilSamlIdp::getIdpIdByAuthMode($a_auth_key);
688  return ilSamlIdp::getInstanceByIdpId($idp_id)->getEntityId();
689 
690  default:
691  $lng->loadLanguageModule('auth');
692  if (!empty($auth_name)) {
693  return $lng->txt('auth_' . $auth_name);
694  }
695 
696  return $lng->txt('auth_' . self::_getAuthModeName($a_auth_key));
697  }
698  }
699 }
const AUTH_OPENID_CONNECT
const AUTH_USER_INACTIVE
static getAuthModeByKey(string $a_auth_key)
Get auth mode by key.
static _generateLogin(string $a_login)
generate free login by starting with a default string and adding postfix numbers
static getAuthModeTranslation(string $a_auth_key, string $auth_name='')
static _getAuthMode(?string $a_auth_mode)
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
static _hasMultipleAuthenticationMethods()
static _getServerList()
Get list of all configured servers.
static getInstanceByServerId(int $a_server_id)
Get instance by server id.
const AUTH_USER_SIMULTANEOUS_LOGIN
const STATUS_AUTHENTICATION_FAILED
static getInstance()
Get singleton instance.
static getKeyByAuthMode(string $a_auth_mode)
Get auth id by auth mode.
Factory for auth frontend classes.
static getServerIdByAuthMode(string $a_auth_mode)
Get auth id by auth mode.
static isAuthenticationForced()
Check if authentication is should be forced.
const AUTH_APACHE_FAILED
const AUTH_USER_WRONG_IP
static goToPublicSection()
go to public section
static supportsLocalPasswordValidation($a_authmode)
Check if local password validation is supported.
static _getActiveAuthModes()
static lookupConsumer(int $a_sid)
Lookup consumer title.
static _getActiveServerList()
Get active server list.
static _needsExternalAccountByAuthMode($a_auth_mode)
Check if chosen auth mode needs an external account entry.
static getInstanceByIdpId(int $a_idp_id)
static getIdpIdByAuthMode(string $a_auth_mode)
static _getAuthModeName($a_auth_key)
static _allowPasswordModificationByAuthMode($a_auth_mode)
Allow password modification.
const AUTH_SOAP_NO_ILIAS_USER_BUT_EMAIL
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
static getServerIdByAuthMode(string $a_auth_mode)
Get auth id by auth mode.
const AUTH_USER_TIME_LIMIT_EXCEEDED
static getAuthPlugins()
Get active enabled auth plugins.
static handleForcedAuthentication()
static getActiveAuthModes()
get all active authmode server ids
static getKeyByAuthMode(string $a_auth_mode)
Get auth id by auth mode.
$GLOBALS["DIC"]
Definition: wac.php:53
global $DIC
Definition: shib_login.php:22
static _isExternalAccountEnabled()
Check if an external account name is required.
static getAllIdps()
static getKeyByAuthMode(string $a_auth_mode)
const AUTH_CAS_NO_ILIAS_USER
static isLocalPasswordEnabledForAuthMode($a_authmode)
Check if local password validation is enabled for a specific auth_mode.
static _getAllAuthModes()
static getAuthModeByKey(string $a_auth_key)
static getInstance()
Get status instance.
global $ilSetting
Definition: privfeed.php:31
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
global $lng
Definition: privfeed.php:31
static _getMultipleAuthModeOptions(ilLanguage $lng)
$server
Definition: shib_login.php:24
static getActiveIdpList()
const AUTH_MODE_INACTIVE
static isPasswordModificationEnabled($a_authmode)
Check if password modification is enabled.
const AUTH_LDAP_NO_ILIAS_USER
const AUTH_SOAP_NO_ILIAS_USER
static getAuthModeByKey(string $a_auth_key)
get auth mode by key
$r