Rev 1306 | Rev 1315 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | daniel-mar | 1 | <?php |
2 | |||
3 | /* |
||
4 | * OIDplus 2.0 |
||
1086 | daniel-mar | 5 | * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft |
2 | daniel-mar | 6 | * |
7 | * Licensed under the Apache License, Version 2.0 (the "License"); |
||
8 | * you may not use this file except in compliance with the License. |
||
9 | * You may obtain a copy of the License at |
||
10 | * |
||
11 | * http://www.apache.org/licenses/LICENSE-2.0 |
||
12 | * |
||
13 | * Unless required by applicable law or agreed to in writing, software |
||
14 | * distributed under the License is distributed on an "AS IS" BASIS, |
||
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||
16 | * See the License for the specific language governing permissions and |
||
17 | * limitations under the License. |
||
18 | */ |
||
19 | |||
1050 | daniel-mar | 20 | namespace ViaThinkSoft\OIDplus; |
511 | daniel-mar | 21 | |
1086 | daniel-mar | 22 | // phpcs:disable PSR1.Files.SideEffects |
23 | \defined('INSIDE_OIDPLUS') or die; |
||
24 | // phpcs:enable PSR1.Files.SideEffects |
||
25 | |||
730 | daniel-mar | 26 | class OIDplusAuthUtils extends OIDplusBaseClass { |
2 | daniel-mar | 27 | |
566 | daniel-mar | 28 | // Useful functions |
29 | |||
1116 | daniel-mar | 30 | /** |
31 | * @param string $password |
||
32 | * @return string |
||
33 | * @throws OIDplusException |
||
34 | */ |
||
1186 | daniel-mar | 35 | private function raPepperProcessing(string $password): string { |
617 | daniel-mar | 36 | // Additional feature: Pepper |
37 | // The pepper is stored inside the base configuration file |
||
38 | // It prevents that an attacker with SQL write rights can |
||
39 | // create accounts. |
||
40 | // ATTENTION!!! If a pepper is used, then the |
||
41 | // hashes are bound to that pepper. If you change the pepper, |
||
42 | // then ALL passwords of RAs become INVALID! |
||
43 | $pepper = OIDplus::baseConfig()->getValue('RA_PASSWORD_PEPPER',''); |
||
44 | if ($pepper !== '') { |
||
711 | daniel-mar | 45 | $algo = OIDplus::baseConfig()->getValue('RA_PASSWORD_PEPPER_ALGO','sha512'); // sha512 works with PHP 7.0 |
46 | if (strtolower($algo) === 'sha3-512') { |
||
47 | $hmac = sha3_512_hmac($password, $pepper); |
||
48 | } else { |
||
49 | $hmac = hash_hmac($algo, $password, $pepper); |
||
50 | } |
||
1116 | daniel-mar | 51 | if ($hmac === "") throw new OIDplusException(_L('HMAC failed')); |
617 | daniel-mar | 52 | return $hmac; |
53 | } else { |
||
54 | return $password; |
||
55 | } |
||
56 | } |
||
57 | |||
585 | daniel-mar | 58 | // Content provider |
577 | daniel-mar | 59 | |
1116 | daniel-mar | 60 | /** |
61 | * @return string |
||
62 | * @throws OIDplusException |
||
63 | */ |
||
1130 | daniel-mar | 64 | public function getAuthMethod(): string { |
585 | daniel-mar | 65 | $acs = $this->getAuthContentStore(); |
66 | if (is_null($acs)) return 'null'; |
||
67 | return get_class($acs); |
||
577 | daniel-mar | 68 | } |
69 | |||
1116 | daniel-mar | 70 | /** |
1305 | daniel-mar | 71 | * @return OIDplusAuthContentStoreJWT|null |
1116 | daniel-mar | 72 | * @throws OIDplusException |
73 | */ |
||
1306 | daniel-mar | 74 | protected function getAuthContentStore()/*: ?OIDplusAuthContentStoreJWT*/ { |
1308 | daniel-mar | 75 | // Sitemap may not make use of any login/logout state |
76 | if ($this->forceAllLoggedOut()) return null; |
||
77 | |||
585 | daniel-mar | 78 | // Logged in via JWT |
1305 | daniel-mar | 79 | // (The JWT can come from a login cookie, an REST Authentication Bearer, an AJAX Cookie, or an Automated AJAX Call GET/POST token.) |
585 | daniel-mar | 80 | $tmp = OIDplusAuthContentStoreJWT::getActiveProvider(); |
81 | if ($tmp) return $tmp; |
||
577 | daniel-mar | 82 | |
585 | daniel-mar | 83 | // No active session and no JWT token available. User is not logged in. |
84 | return null; |
||
577 | daniel-mar | 85 | } |
86 | |||
1116 | daniel-mar | 87 | /** |
88 | * @param string $name |
||
89 | * @param mixed|null $default |
||
90 | * @return mixed |
||
91 | * @throws OIDplusException |
||
92 | */ |
||
93 | public function getExtendedAttribute(string $name, $default=NULL) { |
||
585 | daniel-mar | 94 | $acs = $this->getAuthContentStore(); |
95 | if (is_null($acs)) return $default; |
||
96 | return $acs->getValue($name, $default); |
||
577 | daniel-mar | 97 | } |
98 | |||
566 | daniel-mar | 99 | // RA authentication functions |
2 | daniel-mar | 100 | |
1116 | daniel-mar | 101 | /** |
1308 | daniel-mar | 102 | * "Low level" method for RA Login |
1116 | daniel-mar | 103 | * @param string $email |
104 | * @return void |
||
105 | * @throws OIDplusException |
||
106 | */ |
||
107 | public function raLogin(string $email) { |
||
585 | daniel-mar | 108 | $acs = $this->getAuthContentStore(); |
109 | if (is_null($acs)) return; |
||
1116 | daniel-mar | 110 | $acs->raLogin($email); |
566 | daniel-mar | 111 | } |
2 | daniel-mar | 112 | |
1116 | daniel-mar | 113 | /** |
1308 | daniel-mar | 114 | * "Low level" method for RA Logout |
1116 | daniel-mar | 115 | * @param string $email |
116 | * @return void |
||
117 | * @throws OIDplusException |
||
118 | */ |
||
119 | public function raLogout(string $email) { |
||
585 | daniel-mar | 120 | $acs = $this->getAuthContentStore(); |
121 | if (is_null($acs)) return; |
||
1116 | daniel-mar | 122 | $acs->raLogout($email); |
2 | daniel-mar | 123 | } |
124 | |||
1116 | daniel-mar | 125 | /** |
126 | * @param string $ra_email |
||
127 | * @param string $password |
||
128 | * @return bool |
||
129 | * @throws OIDplusException |
||
130 | */ |
||
131 | public function raCheckPassword(string $ra_email, string $password): bool { |
||
329 | daniel-mar | 132 | $ra = new OIDplusRA($ra_email); |
453 | daniel-mar | 133 | |
617 | daniel-mar | 134 | // Get RA info from RA |
459 | daniel-mar | 135 | $authInfo = $ra->getAuthInfo(); |
590 | daniel-mar | 136 | if (!$authInfo) return false; // user not found |
622 | daniel-mar | 137 | |
617 | daniel-mar | 138 | // Ask plugins if they can verify this hash |
453 | daniel-mar | 139 | $plugins = OIDplus::getAuthPlugins(); |
140 | if (count($plugins) == 0) { |
||
141 | throw new OIDplusException(_L('No RA authentication plugins found')); |
||
142 | } |
||
143 | foreach ($plugins as $plugin) { |
||
1186 | daniel-mar | 144 | if ($plugin->verify($authInfo, $this->raPepperProcessing($password))) return true; |
453 | daniel-mar | 145 | } |
146 | |||
147 | return false; |
||
329 | daniel-mar | 148 | } |
149 | |||
1116 | daniel-mar | 150 | /** |
151 | * @return int |
||
152 | * @throws OIDplusException |
||
153 | */ |
||
154 | public function raNumLoggedIn(): int { |
||
585 | daniel-mar | 155 | $acs = $this->getAuthContentStore(); |
156 | if (is_null($acs)) return 0; |
||
157 | return $acs->raNumLoggedIn(); |
||
85 | daniel-mar | 158 | } |
159 | |||
1116 | daniel-mar | 160 | /** |
161 | * @return OIDplusRA[] |
||
162 | * @throws OIDplusException |
||
163 | */ |
||
164 | public function loggedInRaList(): array { |
||
1308 | daniel-mar | 165 | $acs = $this->getAuthContentStore(); |
166 | if (is_null($acs)) return []; |
||
167 | return $acs->loggedInRaList(); |
||
2 | daniel-mar | 168 | } |
169 | |||
1116 | daniel-mar | 170 | /** |
1267 | daniel-mar | 171 | * @param string|OIDplusRA $ra |
1116 | daniel-mar | 172 | * @return bool |
173 | * @throws OIDplusException |
||
174 | */ |
||
1267 | daniel-mar | 175 | public function isRaLoggedIn($ra): bool { |
176 | $email = $ra instanceof OIDplusRA ? $ra->raEmail() : $ra; |
||
585 | daniel-mar | 177 | $acs = $this->getAuthContentStore(); |
178 | if (is_null($acs)) return false; |
||
179 | return $acs->isRaLoggedIn($email); |
||
2 | daniel-mar | 180 | } |
181 | |||
1308 | daniel-mar | 182 | // "High level" function including logging and checking for valid JWT updates |
1116 | daniel-mar | 183 | |
184 | /** |
||
1308 | daniel-mar | 185 | * "High level" method for RA Login |
1116 | daniel-mar | 186 | * @param string $email |
187 | * @param string $origin |
||
188 | * @return void |
||
189 | * @throws OIDplusException |
||
190 | */ |
||
1305 | daniel-mar | 191 | public function raLoginEx(string $email, string $origin='') { |
585 | daniel-mar | 192 | $loginfo = ''; |
193 | $acs = $this->getAuthContentStore(); |
||
194 | if (!is_null($acs)) { |
||
1301 | daniel-mar | 195 | // User is already logged in (a session or JWT exists), so we modify their login status |
585 | daniel-mar | 196 | $acs->raLoginEx($email, $loginfo); |
197 | $acs->activate(); |
||
198 | } else { |
||
1306 | daniel-mar | 199 | // No user is logged in (no JWT exists). We now create a auth content store and activate it (cookies will be set etc.) |
1305 | daniel-mar | 200 | $newAuthStore = new OIDplusAuthContentStoreJWT(); |
201 | $newAuthStore->setValue(OIDplusAuthContentStoreJWT::CLAIM_GENERATOR, OIDplusAuthContentStoreJWT::JWT_GENERATOR_LOGIN); |
||
1303 | daniel-mar | 202 | $newAuthStore->raLoginEx($email, $loginfo); |
203 | $newAuthStore->activate(); |
||
585 | daniel-mar | 204 | } |
205 | $logmsg = "RA '$email' logged in"; |
||
206 | if ($origin != '') $logmsg .= " via $origin"; |
||
207 | if ($loginfo != '') $logmsg .= " ($loginfo)"; |
||
1267 | daniel-mar | 208 | OIDplus::logger()->log("V2:[OK]RA(%1)", "%2", $email, $logmsg); |
585 | daniel-mar | 209 | } |
210 | |||
1116 | daniel-mar | 211 | /** |
1308 | daniel-mar | 212 | * "High level" method for RA Logout |
1116 | daniel-mar | 213 | * @param string $email |
214 | * @return void |
||
215 | * @throws OIDplusException |
||
216 | */ |
||
217 | public function raLogoutEx(string $email) { |
||
585 | daniel-mar | 218 | $loginfo = ''; |
219 | |||
220 | $acs = $this->getAuthContentStore(); |
||
221 | if (is_null($acs)) return; |
||
1116 | daniel-mar | 222 | $acs->raLogoutEx($email, $loginfo); |
585 | daniel-mar | 223 | |
1267 | daniel-mar | 224 | OIDplus::logger()->log("V2:[OK]RA(%1)", "RA '%1' logged out (%2)", $email, $loginfo); |
585 | daniel-mar | 225 | |
226 | if (($this->raNumLoggedIn() == 0) && (!$this->isAdminLoggedIn())) { |
||
227 | // Nobody logged in anymore. Destroy session cookie to make GDPR people happy |
||
228 | $acs->destroySession(); |
||
229 | } else { |
||
230 | // Get a new token for the remaining users |
||
231 | $acs->activate(); |
||
232 | } |
||
233 | } |
||
234 | |||
14 | daniel-mar | 235 | // Admin authentication functions |
2 | daniel-mar | 236 | |
1116 | daniel-mar | 237 | /** |
1308 | daniel-mar | 238 | * "Low level" method for Admin Login |
1116 | daniel-mar | 239 | * @return void |
240 | * @throws OIDplusException |
||
241 | */ |
||
566 | daniel-mar | 242 | public function adminLogin() { |
585 | daniel-mar | 243 | $acs = $this->getAuthContentStore(); |
244 | if (is_null($acs)) return; |
||
1116 | daniel-mar | 245 | $acs->adminLogin(); |
2 | daniel-mar | 246 | } |
247 | |||
1116 | daniel-mar | 248 | /** |
1308 | daniel-mar | 249 | * "Low level" method for RA Logout |
1116 | daniel-mar | 250 | * @return void |
251 | * @throws OIDplusException |
||
252 | */ |
||
566 | daniel-mar | 253 | public function adminLogout() { |
585 | daniel-mar | 254 | $acs = $this->getAuthContentStore(); |
255 | if (is_null($acs)) return; |
||
1116 | daniel-mar | 256 | $acs->adminLogout(); |
2 | daniel-mar | 257 | } |
258 | |||
1116 | daniel-mar | 259 | /** |
260 | * @param string $password |
||
261 | * @return bool |
||
262 | * @throws OIDplusException |
||
263 | */ |
||
264 | public function adminCheckPassword(string $password): bool { |
||
609 | daniel-mar | 265 | $cfgData = OIDplus::baseConfig()->getValue('ADMIN_PASSWORD', ''); |
266 | if (empty($cfgData)) { |
||
360 | daniel-mar | 267 | throw new OIDplusException(_L('No admin password set in %1','userdata/baseconfig/config.inc.php')); |
261 | daniel-mar | 268 | } |
622 | daniel-mar | 269 | |
609 | daniel-mar | 270 | if (!is_array($cfgData)) { |
271 | $passwordDataArray = array($cfgData); |
||
272 | } else { |
||
1106 | daniel-mar | 273 | $passwordDataArray = $cfgData; // Multiple Administrator passwords |
609 | daniel-mar | 274 | } |
622 | daniel-mar | 275 | |
609 | daniel-mar | 276 | foreach ($passwordDataArray as $passwordData) { |
1107 | daniel-mar | 277 | if (str_starts_with($passwordData, '$')) { |
278 | // Version 3: BCrypt (or any other crypt) |
||
279 | $ok = password_verify($password, $passwordData); |
||
280 | } else if (strpos($passwordData, '$') !== false) { |
||
281 | // Version 2: SHA3-512 with salt |
||
282 | list($salt, $hash) = explode('$', $passwordData, 2); |
||
283 | $ok = hash_equals(sha3_512($salt.$password, true), base64_decode($hash)); |
||
456 | daniel-mar | 284 | } else { |
609 | daniel-mar | 285 | // Version 1: SHA3-512 without salt |
1107 | daniel-mar | 286 | $ok = hash_equals(sha3_512($password, true), base64_decode($passwordData)); |
456 | daniel-mar | 287 | } |
1107 | daniel-mar | 288 | if ($ok) return true; |
421 | daniel-mar | 289 | } |
609 | daniel-mar | 290 | |
291 | return false; |
||
2 | daniel-mar | 292 | } |
293 | |||
1116 | daniel-mar | 294 | /** |
295 | * @return bool |
||
296 | * @throws OIDplusException |
||
297 | */ |
||
298 | public function isAdminLoggedIn(): bool { |
||
1308 | daniel-mar | 299 | $acs = $this->getAuthContentStore(); |
300 | if (is_null($acs)) return false; |
||
301 | return $acs->isAdminLoggedIn(); |
||
2 | daniel-mar | 302 | } |
303 | |||
1116 | daniel-mar | 304 | /** |
1308 | daniel-mar | 305 | * "High level" method for Admin Login |
1116 | daniel-mar | 306 | * @param string $origin |
307 | * @return void |
||
308 | * @throws OIDplusException |
||
309 | */ |
||
1305 | daniel-mar | 310 | public function adminLoginEx(string $origin='') { |
585 | daniel-mar | 311 | $loginfo = ''; |
312 | $acs = $this->getAuthContentStore(); |
||
313 | if (!is_null($acs)) { |
||
1301 | daniel-mar | 314 | // User is already logged in (a session or JWT exists), so we modify their login status |
585 | daniel-mar | 315 | $acs->adminLoginEx($loginfo); |
316 | $acs->activate(); |
||
317 | } else { |
||
1306 | daniel-mar | 318 | // No user is logged in (no JWT exists). We now create a auth content store and activate it (cookies will be set etc.) |
1305 | daniel-mar | 319 | $newAuthStore = new OIDplusAuthContentStoreJWT(); |
320 | $newAuthStore->setValue(OIDplusAuthContentStoreJWT::CLAIM_GENERATOR, OIDplusAuthContentStoreJWT::JWT_GENERATOR_LOGIN); |
||
1303 | daniel-mar | 321 | $newAuthStore->adminLoginEx($loginfo); |
322 | $newAuthStore->activate(); |
||
585 | daniel-mar | 323 | } |
324 | $logmsg = "Admin logged in"; |
||
325 | if ($origin != '') $logmsg .= " via $origin"; |
||
326 | if ($loginfo != '') $logmsg .= " ($loginfo)"; |
||
1267 | daniel-mar | 327 | OIDplus::logger()->log("V2:[OK]A", "%1", $logmsg); |
585 | daniel-mar | 328 | } |
329 | |||
1116 | daniel-mar | 330 | /** |
1308 | daniel-mar | 331 | * "High level" method for Admin Logout |
1116 | daniel-mar | 332 | * @return void |
333 | * @throws OIDplusException |
||
334 | */ |
||
585 | daniel-mar | 335 | public function adminLogoutEx() { |
336 | $loginfo = ''; |
||
337 | |||
338 | $acs = $this->getAuthContentStore(); |
||
339 | if (is_null($acs)) return; |
||
1116 | daniel-mar | 340 | $acs->adminLogoutEx($loginfo); |
585 | daniel-mar | 341 | |
342 | if ($this->raNumLoggedIn() == 0) { |
||
343 | // Nobody here anymore. Destroy the cookie to make GDPR people happy |
||
344 | $acs->destroySession(); |
||
345 | } else { |
||
346 | // Get a new token for the remaining users |
||
347 | $acs->activate(); |
||
348 | } |
||
349 | |||
1267 | daniel-mar | 350 | OIDplus::logger()->log("V2:[OK]A", "Admin logged out (%1)", $loginfo); |
585 | daniel-mar | 351 | } |
352 | |||
1282 | daniel-mar | 353 | // Authentication keys for generating secrets or validating arguments (e.g. sent by mail) |
2 | daniel-mar | 354 | |
1116 | daniel-mar | 355 | /** |
1283 | daniel-mar | 356 | * @param array|string $data |
1116 | daniel-mar | 357 | * @return string |
358 | * @throws OIDplusException |
||
359 | */ |
||
1283 | daniel-mar | 360 | public function makeSecret($data): string { |
361 | if (!is_array($data)) $data = [$data]; |
||
362 | $data = json_encode($data); |
||
1282 | daniel-mar | 363 | return sha3_512_hmac($data, 'OIDplus:'.OIDplus::baseConfig()->getValue('SERVER_SECRET'), false); |
364 | } |
||
365 | |||
366 | /** |
||
1283 | daniel-mar | 367 | * @param array|string $data Arbitary data to be validated later |
368 | * @return string A string that need to be validated with validateAuthKey |
||
1282 | daniel-mar | 369 | * @throws OIDplusException |
370 | */ |
||
1283 | daniel-mar | 371 | public function makeAuthKey($data): string { |
372 | if (!is_array($data)) $data = [$data]; |
||
373 | $ts = time(); |
||
374 | $data_ext = [$ts, $data]; |
||
375 | $secret = $this->makeSecret($data_ext); |
||
376 | return $ts.'.'.$secret; |
||
2 | daniel-mar | 377 | } |
378 | |||
1116 | daniel-mar | 379 | /** |
1283 | daniel-mar | 380 | * @param array|string $data The original data that had been passed to makeAuthKey() |
381 | * @param string $auth_key The result from makeAuthKey() |
||
382 | * @param int $valid_secs How many seconds is the auth key valid? (-1 for infinite) |
||
383 | * @return bool True if the key is valid and not expired. |
||
1116 | daniel-mar | 384 | * @throws OIDplusException |
385 | */ |
||
1283 | daniel-mar | 386 | public function validateAuthKey($data, string $auth_key, int $valid_secs=-1): bool { |
387 | $auth_key_ary = explode('.', $auth_key, 2); |
||
388 | if (count($auth_key_ary) != 2) return false; // invalid auth key syntax |
||
389 | list($ts, $secret) = $auth_key_ary; |
||
390 | if (!is_numeric($ts)) return false; // invalid auth key syntax |
||
391 | if ($valid_secs >= 0) { |
||
392 | if (time() > ($ts+$valid_secs)) return false; // expired auth key |
||
393 | } |
||
394 | if (!is_array($data)) $data = [$data]; |
||
395 | $data_ext = [(int)$ts, $data]; |
||
396 | return hash_equals($this->makeSecret($data_ext), $secret); |
||
2 | daniel-mar | 397 | } |
398 | |||
329 | daniel-mar | 399 | // "Veto" functions to force logout state |
400 | |||
1116 | daniel-mar | 401 | /** |
402 | * @return bool |
||
403 | */ |
||
404 | protected function forceAllLoggedOut(): bool { |
||
329 | daniel-mar | 405 | if (isset($_SERVER['SCRIPT_FILENAME']) && (basename($_SERVER['SCRIPT_FILENAME']) == 'sitemap.php')) { |
406 | // The sitemap may not contain any confidential information, |
||
407 | // even if the user is logged in, because the admin could |
||
408 | // accidentally copy-paste the sitemap to a |
||
409 | // search engine control panel while they are logged in |
||
410 | return true; |
||
411 | } else { |
||
412 | return false; |
||
413 | } |
||
414 | } |
||
427 | daniel-mar | 415 | |
424 | daniel-mar | 416 | // CSRF functions |
427 | daniel-mar | 417 | |
424 | daniel-mar | 418 | private $enable_csrf = true; |
427 | daniel-mar | 419 | |
1116 | daniel-mar | 420 | /** |
421 | * @return void |
||
422 | */ |
||
424 | daniel-mar | 423 | public function enableCSRF() { |
424 | $this->enable_csrf = true; |
||
425 | } |
||
427 | daniel-mar | 426 | |
1116 | daniel-mar | 427 | /** |
428 | * @return void |
||
429 | */ |
||
424 | daniel-mar | 430 | public function disableCSRF() { |
431 | $this->enable_csrf = false; |
||
432 | } |
||
427 | daniel-mar | 433 | |
1116 | daniel-mar | 434 | /** |
435 | * @return string |
||
436 | * @throws \Random\RandomException |
||
437 | */ |
||
438 | public function genCSRFToken(): string { |
||
1098 | daniel-mar | 439 | return random_bytes_ex(64, false, false); |
424 | daniel-mar | 440 | } |
427 | daniel-mar | 441 | |
1116 | daniel-mar | 442 | /** |
443 | * @return void |
||
444 | * @throws OIDplusException |
||
445 | */ |
||
424 | daniel-mar | 446 | public function checkCSRF() { |
427 | daniel-mar | 447 | if (!$this->enable_csrf) return; |
866 | daniel-mar | 448 | |
1130 | daniel-mar | 449 | $request_token = $_REQUEST['csrf_token'] ?? ''; |
450 | $cookie_token = $_COOKIE['csrf_token'] ?? ''; |
||
866 | daniel-mar | 451 | |
452 | if (empty($request_token) || empty($cookie_token) || ($request_token !== $cookie_token)) { |
||
453 | if (OIDplus::baseConfig()->getValue('DEBUG')) { |
||
454 | throw new OIDplusException(_L('Missing or wrong CSRF Token: Request %1 vs Cookie %2', |
||
455 | isset($_REQUEST['csrf_token']) ? '"'.$_REQUEST['csrf_token'].'"' : 'NULL', |
||
1130 | daniel-mar | 456 | $_COOKIE['csrf_token'] ?? 'NULL' |
866 | daniel-mar | 457 | )); |
458 | } else { |
||
459 | throw new OIDplusException(_L('Missing or wrong "CSRF Token". To fix the issue, try clearing your browser cache and reload the page. If you visited the page via HTTPS before, try HTTPS in case you are currently connected via HTTP.')); |
||
460 | } |
||
424 | daniel-mar | 461 | } |
462 | } |
||
329 | daniel-mar | 463 | |
421 | daniel-mar | 464 | // Generate RA passwords |
622 | daniel-mar | 465 | |
1116 | daniel-mar | 466 | /** |
467 | * @param string $password |
||
468 | * @return OIDplusRAAuthInfo |
||
469 | * @throws OIDplusException |
||
470 | */ |
||
1186 | daniel-mar | 471 | public function raGeneratePassword(string $password): OIDplusRAAuthInfo { |
1099 | daniel-mar | 472 | $plugin = OIDplus::getDefaultRaAuthPlugin(true); |
1186 | daniel-mar | 473 | return $plugin->generate($this->raPepperProcessing($password)); |
421 | daniel-mar | 474 | } |
475 | |||
476 | // Generate admin password |
||
477 | |||
585 | daniel-mar | 478 | /* Nothing here; the admin password will be generated in setup_base.js , purely in the web-browser */ |
421 | daniel-mar | 479 | |
480 | } |