ILIAS  trunk Revision v11.0_alpha-1723-g8e69f309bab
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
class.ilAuthProviderOpenIdConnect.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
24 {
25  private const OIDC_AUTH_IDTOKEN = 'oidc_auth_idtoken';
26 
29  private readonly ilLogger $logger;
30  private readonly ilLanguage $lng;
31 
33  {
34  global $DIC;
35  parent::__construct($credentials);
36 
37  $this->logger = $DIC->logger()->auth();
39  $this->lng = $DIC->language();
40  $this->lng->loadLanguageModule('auth');
41  }
42 
43  public function handleLogout(): void
44  {
45  if ($this->settings->getLogoutScope() === ilOpenIdConnectSettings::LOGOUT_SCOPE_LOCAL) {
46  return;
47  }
48 
49  $id_token = ilSession::get(self::OIDC_AUTH_IDTOKEN);
50  $this->logger->debug('Logging out with token: ' . $id_token);
51 
52  if (isset($id_token) && $id_token !== '') {
53  ilSession::set(self::OIDC_AUTH_IDTOKEN, '');
54  $oidc = $this->initClient();
55  try {
56  $oidc->signOut(
57  $id_token,
58  ILIAS_HTTP_PATH . '/' . ilStartUpGUI::logoutUrl()
59  );
60  } catch (\Jumbojett\OpenIDConnectClientException $e) {
61  $this->logger->warning('Logging out of OIDC provider failed with: ' . $e->getMessage());
62  }
63  }
64  }
65 
66  public function doAuthentication(ilAuthStatus $status): bool
67  {
68  try {
69  $oidc = $this->initClient();
70  $oidc->setRedirectURL(ILIAS_HTTP_PATH . '/openidconnect.php');
71 
73  if ($proxy->isActive()) {
74  $host = $proxy->getHost();
75  $port = $proxy->getPort();
76  if ($port) {
77  $host .= ':' . $port;
78  }
79  $oidc->setHttpProxy($host);
80  }
81 
82  $this->logger->debug(
83  'Redirect url is: ' .
84  $oidc->getRedirectURL()
85  );
86 
87  $oidc->addScope($this->settings->getAllScopes());
88  if ($this->settings->getLoginPromptType() === ilOpenIdConnectSettings::LOGIN_ENFORCE) {
89  $oidc->addAuthParam(['prompt' => 'login']);
90  }
91 
92  $oidc->authenticate();
93  // user is authenticated, otherwise redirected to authorization endpoint or exception
94 
95  $claims = $oidc->getVerifiedClaims();
96  $this->logger->dump($claims, ilLogLevel::DEBUG);
97  $status = $this->handleUpdate($status, $claims);
98 
99  // @todo : provide a general solution for all authentication methods
100  //$_GET['target'] = $this->getCredentials()->getRedirectionTarget();// TODO PHP8-REVIEW Please eliminate this. Mutating the request is not allowed and will not work in ILIAS 8.
101 
102  if ($this->settings->getLogoutScope() === ilOpenIdConnectSettings::LOGOUT_SCOPE_GLOBAL) {
103  ilSession::set(self::OIDC_AUTH_IDTOKEN, $oidc->getIdToken());
104  }
105  return true;
106  } catch (Exception $e) {
107  $this->logger->warning($e->getMessage());
108  $this->logger->warning((string) $e->getCode());
110  $status->setTranslatedReason($this->lng->txt('auth_oidc_failed'));
111  return false;
112  }
113  }
114 
118  private function handleUpdate(ilAuthStatus $status, $user_info): ilAuthStatus
119  {
120  if (!is_object($user_info)) {
121  $this->logger->error('Received invalid user credentials: ');
122  $this->logger->dump($user_info, ilLogLevel::ERROR);
124  $status->setReason('err_wrong_login');
125  return $status;
126  }
127 
128  $uid_field = $this->settings->getUidField();
129  $ext_account = $user_info->{$uid_field} ?? '';
130 
131  if (!is_string($ext_account) || $ext_account === '') {
132  $this->logger->error('Could not determine valid external account, value is empty or not a string.');
133  $this->logger->dump($user_info, ilLogLevel::ERROR);
135  $status->setReason('err_wrong_login');
136  return $status;
137  }
138 
139  $this->logger->debug('Authenticated external account: ' . $ext_account);
140 
143  $ext_account
144  );
145 
146  try {
147  $sync = new ilOpenIdConnectUserSync($this->settings, $user_info);
148  $sync->setExternalAccount($ext_account);
149  $sync->setInternalAccount((string) $int_account);
150  $sync->updateUser();
151 
152  $user_id = $sync->getUserId();
153  ilSession::set('used_external_auth_mode', ilAuthUtils::AUTH_OPENID_CONNECT);
154  $status->setAuthenticatedUserId($user_id);
156  //$_GET['target'] = $this->getCredentials()->getRedirectionTarget();// TODO PHP8-REVIEW Please eliminate this. Mutating the request is not allowed and will not work in ILIAS 8.
159  $status->setReason('err_wrong_login');
160  }
161 
162  return $status;
163  }
164 
165  private function initClient(): OpenIDConnectClient
166  {
167  $oidc = new OpenIDConnectClient(
168  $this->settings->getProvider(),
169  $this->settings->getClientId(),
170  $this->settings->getSecret()
171  );
172 
173  $oidc->setCodeChallengeMethod('S256');
174 
175  return $oidc;
176  }
177 }
const AUTH_OPENID_CONNECT
static get(string $a_var)
Interface of auth credentials.
const STATUS_AUTHENTICATION_FAILED
static _checkExternalAuthAccount(string $a_auth, string $a_account, bool $tryFallback=true)
check whether external account and authentication method matches with a user
$claims
Definition: ltitoken.php:68
Base class for authentication providers (ldap, apache, ...)
static logoutUrl(array $parameters=[])
Return the logout URL with a valid CSRF token.
setStatus(int $a_status)
Set auth status.
global $DIC
Definition: shib_login.php:22
ilAuthCredentials $credentials
readonly ilOpenIdConnectSettings $settings
__construct(Container $dic, ilPlugin $plugin)
handleUpdate(ilAuthStatus $status, $user_info)
setTranslatedReason(string $a_reason)
Set translated reason.
setReason(string $a_reason)
Set reason.
Auth status implementation.
__construct(ilAuthCredentials $credentials)
static set(string $a_var, $a_val)
Set a value.