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