ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilAuthProviderOpenIdConnect.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
21use Jumbojett\OpenIDConnectClient;
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;
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);
155 $status->setStatus(ilAuthStatus::STATUS_AUTHENTICATED);
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}
readonly ilOpenIdConnectSettings $settings
handleUpdate(ilAuthStatus $status, $user_info)
__construct(ilAuthCredentials $credentials)
ilAuthCredentials $credentials
setTranslatedReason(string $a_reason)
Set translated reason.
const int STATUS_AUTHENTICATION_FAILED
setReason(string $a_reason)
Set reason.
setStatus(int $a_status)
Set auth status.
const int STATUS_AUTHENTICATED
const int AUTH_OPENID_CONNECT
language handling
Component logger with individual log levels by component id.
static _checkExternalAuthAccount(string $a_auth, string $a_account, bool $tryFallback=true)
check whether external account and authentication method matches with a user
static get(string $a_var)
static set(string $a_var, $a_val)
Set a value.
static logoutUrl(array $parameters=[])
Return the logout URL with a valid CSRF token.
$claims
Definition: ltitoken.php:68
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
global $DIC
Definition: shib_login.php:26