Rev 1303 | Rev 1306 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1303 | Rev 1305 | ||
---|---|---|---|
Line 22... | Line 22... | ||
22 | // phpcs:disable PSR1.Files.SideEffects |
22 | // phpcs:disable PSR1.Files.SideEffects |
23 | \defined('INSIDE_OIDPLUS') or die; |
23 | \defined('INSIDE_OIDPLUS') or die; |
24 | // phpcs:enable PSR1.Files.SideEffects |
24 | // phpcs:enable PSR1.Files.SideEffects |
25 | 25 | ||
26 | /** |
26 | /** |
27 | * Auth content store for JWT tokens ("Remember me" cookies, Automated AJAX argument, or REST Bearer) |
27 | * Auth content store for JWT tokens (web browser login cookies, Automated AJAX argument, or REST Bearer) |
28 | */ |
28 | */ |
29 | class OIDplusAuthContentStoreJWT extends OIDplusAuthContentStore { |
29 | class OIDplusAuthContentStoreJWT { |
30 | 30 | ||
31 | /** |
31 | /** |
32 | * Cookie name for the JWT auth token |
32 | * Cookie name for the JWT auth token |
33 | */ |
33 | */ |
34 | const COOKIE_NAME = 'OIDPLUS_AUTH_JWT'; |
34 | const COOKIE_NAME = 'OIDPLUS_AUTH_JWT'; |
35 | 35 | ||
36 | /** |
36 | /** |
- | 37 | * Token generator; must be one of OIDplusAuthContentStoreJWT::JWT_GENERATOR_* |
|
- | 38 | */ |
|
- | 39 | const CLAIM_GENERATOR = 'urn:oid:1.3.6.1.4.1.37476.2.5.2.7.1'; |
|
- | 40 | ||
- | 41 | /** |
|
- | 42 | * List of logged-in users |
|
- | 43 | */ |
|
- | 44 | const CLAIM_LOGIN_LIST = 'urn:oid:1.3.6.1.4.1.37476.2.5.2.7.2'; |
|
- | 45 | ||
- | 46 | /** |
|
- | 47 | * SSH = Server Secret Hash |
|
- | 48 | */ |
|
- | 49 | const CLAIM_SSH = 'urn:oid:1.3.6.1.4.1.37476.2.5.2.7.3'; |
|
- | 50 | ||
- | 51 | /** |
|
- | 52 | * IP-Adress limit |
|
- | 53 | */ |
|
- | 54 | const CLAIM_LIMIT_IP = 'urn:oid:1.3.6.1.4.1.37476.2.5.2.7.4'; |
|
- | 55 | ||
- | 56 | /** |
|
37 | * "Automated AJAX" plugin |
57 | * "Automated AJAX" plugin |
38 | */ |
58 | */ |
39 | const JWT_GENERATOR_AJAX = 10; |
59 | const JWT_GENERATOR_AJAX = 10; |
40 | /** |
60 | /** |
41 | * "REST API" plugin |
61 | * "REST API" plugin |
42 | */ |
62 | */ |
43 | const JWT_GENERATOR_REST = 20; |
63 | const JWT_GENERATOR_REST = 20; |
44 | /** |
64 | /** |
45 | * "Remember me" login method |
65 | * Web browser login method |
46 | */ |
66 | */ |
47 | const JWT_GENERATOR_LOGIN = 40; |
67 | const JWT_GENERATOR_LOGIN = 40; |
48 | /** |
68 | /** |
49 | * "Manually crafted" JWT tokens |
69 | * "Manually crafted" JWT tokens |
50 | */ |
70 | */ |
Line 65... | Line 85... | ||
65 | */ |
85 | */ |
66 | private static function generatorName($gen) { |
86 | private static function generatorName($gen) { |
67 | // Note: The strings are not translated, because the name is used in config keys or logs |
87 | // Note: The strings are not translated, because the name is used in config keys or logs |
68 | if ($gen === self::JWT_GENERATOR_AJAX) return 'Automated AJAX calls'; |
88 | if ($gen === self::JWT_GENERATOR_AJAX) return 'Automated AJAX calls'; |
69 | if ($gen === self::JWT_GENERATOR_REST) return 'REST API'; |
89 | if ($gen === self::JWT_GENERATOR_REST) return 'REST API'; |
70 | if ($gen === self::JWT_GENERATOR_LOGIN) return 'Login ("Remember me")'; |
90 | if ($gen === self::JWT_GENERATOR_LOGIN) return 'Browser login'; |
71 | if ($gen === self::JWT_GENERATOR_MANUAL) return 'Manually created'; |
91 | if ($gen === self::JWT_GENERATOR_MANUAL) return 'Manually created'; |
72 | return 'Unknown generator'; |
92 | return 'Unknown generator'; |
73 | } |
93 | } |
74 | 94 | ||
75 | /** |
95 | /** |
Line 82... | Line 102... | ||
82 | $cfg = self::jwtGetBlacklistConfigKey($gen, $sub); |
102 | $cfg = self::jwtGetBlacklistConfigKey($gen, $sub); |
83 | $bl_time = time()-1; |
103 | $bl_time = time()-1; |
84 | 104 | ||
85 | $gen_desc = self::generatorName($gen); |
105 | $gen_desc = self::generatorName($gen); |
86 | 106 | ||
87 | OIDplus::config()->prepareConfigKey($cfg, 'Revoke timestamp of all JWT tokens for $sub with generator $gen ($gen_desc)', "$bl_time", OIDplusConfig::PROTECTION_HIDDEN, function($value) {}); |
107 | OIDplus::config()->prepareConfigKey($cfg, "Revoke timestamp of all JWT tokens for $sub with generator $gen ($gen_desc)", "$bl_time", OIDplusConfig::PROTECTION_HIDDEN, function($value) {}); |
88 | OIDplus::config()->setValue($cfg, $bl_time); |
108 | OIDplus::config()->setValue($cfg, $bl_time); |
89 | } |
109 | } |
90 | 110 | ||
91 | /** |
111 | /** |
92 | * @param int $gen OIDplusAuthContentStoreJWT::JWT_GENERATOR_... |
112 | * @param int $gen OIDplusAuthContentStoreJWT::JWT_GENERATOR_... |
Line 103... | Line 123... | ||
103 | * We include a hash of the server-secret here (ssh = server-secret-hash), so that the JWT can be invalidated by changing the server-secret |
123 | * We include a hash of the server-secret here (ssh = server-secret-hash), so that the JWT can be invalidated by changing the server-secret |
104 | * @return string |
124 | * @return string |
105 | * @throws OIDplusException |
125 | * @throws OIDplusException |
106 | */ |
126 | */ |
107 | private static function getSsh(): string { |
127 | private static function getSsh(): string { |
108 | return OIDplus::authUtils()->makeSecret(['bb1aebd6-fe6a-11ed-a553-3c4a92df8582']); |
128 | $hexadecimal_string = OIDplus::authUtils()->makeSecret(['bb1aebd6-fe6a-11ed-a553-3c4a92df8582']); |
- | 129 | return base64_encode(pack('H*',$hexadecimal_string)); |
|
109 | } |
130 | } |
110 | 131 | ||
111 | /** |
132 | /** |
112 | * Do various checks if the token is allowed and not blacklisted |
133 | * Do various checks if the token is allowed and not blacklisted |
113 | * @param OIDplusAuthContentStore $contentProvider |
134 | * @param OIDplusAuthContentStoreJWT $contentProvider |
114 | * @param int|null $validGenerators Bitmask which generators to allow (null = allow all) |
135 | * @param int|null $validGenerators Bitmask which generators to allow (null = allow all) |
115 | * @return void |
136 | * @return void |
116 | * @throws OIDplusException |
137 | * @throws OIDplusException |
117 | */ |
138 | */ |
118 | private static function jwtSecurityCheck(OIDplusAuthContentStore $contentProvider, int $validGenerators=null) { |
139 | private static function jwtSecurityCheck(OIDplusAuthContentStoreJWT $contentProvider, int $validGenerators=null) { |
119 | // Check if the token is intended for us |
140 | // Check if the token is intended for us |
120 | if ($contentProvider->getValue('aud','') !== OIDplus::getEditionInfo()['jwtaud']) { |
141 | if ($contentProvider->getValue('aud','') !== OIDplus::getEditionInfo()['jwtaud']) { |
121 | throw new OIDplusException(_L('Token has wrong audience')); |
142 | throw new OIDplusException(_L('Token has wrong audience')); |
122 | } |
143 | } |
123 | 144 | ||
124 | if ($contentProvider->getValue('oidplus_ssh', '') !== self::getSsh()) { |
145 | if ($contentProvider->getValue(self::CLAIM_SSH, '') !== self::getSsh()) { |
125 | throw new OIDplusException(_L('"Server Secret" was changed; therefore the JWT is not valid anymore')); |
146 | throw new OIDplusException(_L('"Server Secret" was changed; therefore the JWT is not valid anymore')); |
126 | } |
147 | } |
127 | 148 | ||
128 | $gen = $contentProvider->getValue('oidplus_generator', -1); |
149 | $gen = $contentProvider->getValue(self::CLAIM_GENERATOR, -1); |
129 | 150 | ||
130 | $has_admin = $contentProvider->isAdminLoggedIn(); |
151 | $has_admin = $contentProvider->isAdminLoggedIn(); |
131 | $has_ra = $contentProvider->raNumLoggedIn() > 0; |
152 | $has_ra = $contentProvider->raNumLoggedIn() > 0; |
132 | 153 | ||
133 | // Check if the token generator is allowed |
154 | // Check if the token generator is allowed |
Line 150... | Line 171... | ||
150 | // Generator: plugins/viathinksoft/raPages/911_rest_api/OIDplusPageRaRestApi.class.php |
171 | // Generator: plugins/viathinksoft/raPages/911_rest_api/OIDplusPageRaRestApi.class.php |
151 | throw new OIDplusException(_L('The administrator has disabled this feature. (Base configuration setting %1).','JWT_ALLOW_REST_USER')); |
172 | throw new OIDplusException(_L('The administrator has disabled this feature. (Base configuration setting %1).','JWT_ALLOW_REST_USER')); |
152 | } |
173 | } |
153 | } |
174 | } |
154 | else if ($gen === self::JWT_GENERATOR_LOGIN) { |
175 | else if ($gen === self::JWT_GENERATOR_LOGIN) { |
155 | // Used for feature "Remember me" (use JWT token in a cookie as alternative to PHP session): |
176 | // Used for web browser login (use JWT token in a cookie as alternative to PHP session): |
156 | // - No PHP session will be used |
177 | // - No PHP session will be used |
157 | // - Session will not be bound to IP address (therefore, you can switch between mobile/WiFi for example) |
178 | // - Session will not be bound to IP address (therefore, you can switch between mobile/WiFi for example) |
158 | // - No server-side session needed |
179 | // - No server-side session needed |
159 | if (($has_admin) && !OIDplus::baseConfig()->getValue('JWT_ALLOW_LOGIN_ADMIN', true)) { |
180 | if (($has_admin) && !OIDplus::baseConfig()->getValue('JWT_ALLOW_LOGIN_ADMIN', true)) { |
160 | throw new OIDplusException(_L('The administrator has disabled this feature. (Base configuration setting %1).','JWT_ALLOW_LOGIN_ADMIN')); |
181 | throw new OIDplusException(_L('The administrator has disabled this feature. (Base configuration setting %1).','JWT_ALLOW_LOGIN_ADMIN')); |
Line 175... | Line 196... | ||
175 | throw new OIDplusException(_L('Token generator %1 not recognized',$gen)); |
196 | throw new OIDplusException(_L('Token generator %1 not recognized',$gen)); |
176 | } |
197 | } |
177 | 198 | ||
178 | // Make sure that the IAT (issued at time) isn't in a blacklisted timeframe |
199 | // Make sure that the IAT (issued at time) isn't in a blacklisted timeframe |
179 | // When an user believes that a token was compromised, then they can blacklist the tokens identified by their "iat" ("Issued at") property |
200 | // When an user believes that a token was compromised, then they can blacklist the tokens identified by their "iat" ("Issued at") property |
180 | // When a user logs out of a "remember me" session, the JWT token will be blacklisted as well |
201 | // When a user logs out of a web browser session, the JWT token will be blacklisted as well |
181 | // Small side effect: All "remember me" sessions of that user will be revoked then |
202 | // Small side effect: All web browser login sessions of that user will be revoked then |
182 | $iat = $contentProvider->getValue('iat',0); |
203 | $iat = $contentProvider->getValue('iat',0); |
183 | if (($iat-120/*leeway 2min*/) > time()) { |
204 | if (($iat-120/*leeway 2min*/) > time()) { |
184 | // Token was created in the future. Something is wrong! |
205 | // Token was created in the future. Something is wrong! |
185 | throw new OIDplusException(_L('JWT Token cannot be verified because the server time is wrong')); |
206 | throw new OIDplusException(_L('JWT Token cannot be verified because the server time is wrong')); |
186 | } |
207 | } |
Line 198... | Line 219... | ||
198 | } |
219 | } |
199 | } |
220 | } |
200 | 221 | ||
201 | // Optional feature: Limit the JWT to a specific IP address |
222 | // Optional feature: Limit the JWT to a specific IP address |
202 | // Currently not used in OIDplus |
223 | // Currently not used in OIDplus |
203 | $ip = $contentProvider->getValue('oidplus_limit_ip',''); |
224 | $ip = $contentProvider->getValue(self::CLAIM_LIMIT_IP, null); |
204 | if ($ip !== '') { |
225 | if (!is_null($ip)) { |
205 | if (isset($_SERVER['REMOTE_ADDR']) && ($ip !== $_SERVER['REMOTE_ADDR'])) { |
226 | if (isset($_SERVER['REMOTE_ADDR']) && ($ip !== $_SERVER['REMOTE_ADDR'])) { |
206 | throw new OIDplusException(_L('Your IP address is not allowed to use this token')); |
227 | throw new OIDplusException(_L('Your IP address is not allowed to use this token')); |
207 | } |
228 | } |
208 | } |
229 | } |
209 | 230 | ||
Line 280... | Line 301... | ||
280 | */ |
301 | */ |
281 | public function destroySession() { |
302 | public function destroySession() { |
282 | OIDplus::cookieUtils()->unsetcookie(self::COOKIE_NAME); |
303 | OIDplus::cookieUtils()->unsetcookie(self::COOKIE_NAME); |
283 | } |
304 | } |
284 | 305 | ||
- | 306 | // RA authentication functions (low-level) |
|
- | 307 | ||
- | 308 | /** |
|
- | 309 | * @param string $email |
|
- | 310 | * @return void |
|
- | 311 | */ |
|
- | 312 | public function raLogin(string $email) { |
|
- | 313 | if ($email == 'admin') return; |
|
- | 314 | ||
- | 315 | $list = $this->getValue(self::CLAIM_LOGIN_LIST, null); |
|
- | 316 | if (is_null($list)) $list = []; |
|
- | 317 | if (!in_array($email, $list)) $list[] = $email; |
|
- | 318 | $this->setValue(self::CLAIM_LOGIN_LIST, $list); |
|
- | 319 | } |
|
- | 320 | ||
- | 321 | /** |
|
- | 322 | * @return int |
|
- | 323 | */ |
|
- | 324 | public function raNumLoggedIn(): int { |
|
- | 325 | return count($this->loggedInRaList()); |
|
- | 326 | } |
|
- | 327 | ||
- | 328 | /** |
|
- | 329 | * @return OIDplusRA[] |
|
- | 330 | */ |
|
- | 331 | public function loggedInRaList(): array { |
|
- | 332 | $list = $this->getValue(self::CLAIM_LOGIN_LIST, null); |
|
- | 333 | if (is_null($list)) $list = []; |
|
- | 334 | ||
- | 335 | $res = array(); |
|
- | 336 | foreach (array_unique($list) as $username) { |
|
- | 337 | if ($username == '') continue; // should not happen |
|
- | 338 | if ($username == 'admin') continue; |
|
- | 339 | $res[] = new OIDplusRA($username); |
|
- | 340 | } |
|
- | 341 | return $res; |
|
- | 342 | } |
|
- | 343 | ||
- | 344 | /** |
|
- | 345 | * @param string $email |
|
- | 346 | * @return bool |
|
- | 347 | */ |
|
- | 348 | public function isRaLoggedIn(string $email): bool { |
|
- | 349 | foreach ($this->loggedInRaList() as $ra) { |
|
- | 350 | if ($email == $ra->raEmail()) return true; |
|
- | 351 | } |
|
- | 352 | return false; |
|
- | 353 | } |
|
- | 354 | ||
285 | /** |
355 | /** |
286 | * @param string $email |
356 | * @param string $email |
287 | * @return void |
357 | * @return void |
288 | * @throws OIDplusException |
358 | * @throws OIDplusException |
289 | */ |
359 | */ |
290 | public function raLogout(string $email) { |
360 | public function raLogout(string $email) { |
- | 361 | if ($email == 'admin') return; |
|
- | 362 | ||
291 | $gen = $this->getValue('oidplus_generator', -1); |
363 | $gen = $this->getValue(self::CLAIM_GENERATOR, -1); |
292 | if ($gen >= 0) self::jwtBlacklist($gen, $email); |
364 | if ($gen >= 0) self::jwtBlacklist($gen, $email); |
- | 365 | ||
- | 366 | $list = $this->getValue(self::CLAIM_LOGIN_LIST, null); |
|
- | 367 | if (is_null($list)) $list = []; |
|
293 | parent::raLogout($email); |
368 | $key = array_search($email, $list); |
- | 369 | if ($key !== false) unset($list[$key]); |
|
- | 370 | $this->setValue(self::CLAIM_LOGIN_LIST, $list); |
|
294 | } |
371 | } |
295 | 372 | ||
296 | /** |
373 | /** |
297 | * @param string $email |
374 | * @param string $email |
298 | * @param string $loginfo |
375 | * @param string $loginfo |
Line 302... | Line 379... | ||
302 | public function raLogoutEx(string $email, string &$loginfo) { |
379 | public function raLogoutEx(string $email, string &$loginfo) { |
303 | $this->raLogout($email); |
380 | $this->raLogout($email); |
304 | $loginfo = 'from JWT session'; |
381 | $loginfo = 'from JWT session'; |
305 | } |
382 | } |
306 | 383 | ||
- | 384 | // Admin authentication functions (low-level) |
|
- | 385 | ||
- | 386 | /** |
|
- | 387 | * @return void |
|
- | 388 | */ |
|
- | 389 | public function adminLogin() { |
|
- | 390 | $list = $this->getValue(self::CLAIM_LOGIN_LIST, null); |
|
- | 391 | if (is_null($list)) $list = []; |
|
- | 392 | if (!in_array('admin', $list)) $list[] = 'admin'; |
|
- | 393 | $this->setValue(self::CLAIM_LOGIN_LIST, $list); |
|
- | 394 | } |
|
- | 395 | ||
- | 396 | /** |
|
- | 397 | * @return bool |
|
- | 398 | */ |
|
- | 399 | public function isAdminLoggedIn(): bool { |
|
- | 400 | $list = $this->getValue(self::CLAIM_LOGIN_LIST, null); |
|
- | 401 | if (is_null($list)) $list = []; |
|
- | 402 | return in_array('admin', $list); |
|
- | 403 | } |
|
- | 404 | ||
307 | /** |
405 | /** |
308 | * @return void |
406 | * @return void |
309 | * @throws OIDplusException |
407 | * @throws OIDplusException |
310 | */ |
408 | */ |
311 | public function adminLogout() { |
409 | public function adminLogout() { |
312 | $gen = $this->getValue('oidplus_generator', -1); |
410 | $gen = $this->getValue(self::CLAIM_GENERATOR, -1); |
313 | if ($gen >= 0) self::jwtBlacklist($gen, 'admin'); |
411 | if ($gen >= 0) self::jwtBlacklist($gen, 'admin'); |
- | 412 | ||
- | 413 | $list = $this->getValue(self::CLAIM_LOGIN_LIST, null); |
|
- | 414 | if (is_null($list)) $list = []; |
|
314 | parent::adminLogout(); |
415 | $key = array_search('admin', $list); |
- | 416 | if ($key !== false) unset($list[$key]); |
|
- | 417 | $this->setValue(self::CLAIM_LOGIN_LIST, $list); |
|
315 | } |
418 | } |
316 | 419 | ||
317 | /** |
420 | /** |
318 | * @param string $loginfo |
421 | * @param string $loginfo |
319 | * @return void |
422 | * @return void |
Line 325... | Line 428... | ||
325 | } |
428 | } |
326 | 429 | ||
327 | private static $contentProvider = null; |
430 | private static $contentProvider = null; |
328 | 431 | ||
329 | /** |
432 | /** |
330 | * @return OIDplusAuthContentStore|null |
433 | * @return OIDplusAuthContentStoreJWT|null |
331 | * @throws OIDplusException |
434 | * @throws OIDplusException |
332 | */ |
435 | */ |
333 | public static function getActiveProvider()/*: ?OIDplusAuthContentStore*/ { |
436 | public static function getActiveProvider()/*: ?OIDplusAuthContentStoreJWT*/ { |
334 | if (!self::$contentProvider) { |
437 | if (!self::$contentProvider) { |
335 | 438 | ||
336 | $tmp = null; |
439 | $tmp = null; |
337 | $silent_error = false; |
440 | $silent_error = false; |
338 | 441 | ||
Line 350... | Line 453... | ||
350 | self::jwtSecurityCheck($tmp, self::JWT_GENERATOR_REST | self::JWT_GENERATOR_MANUAL); |
453 | self::jwtSecurityCheck($tmp, self::JWT_GENERATOR_REST | self::JWT_GENERATOR_MANUAL); |
351 | } |
454 | } |
352 | 455 | ||
353 | } else { |
456 | } else { |
354 | 457 | ||
355 | // A web-visitor (HTML and AJAX, but not REST) can use a JWT "remember me" Cookie |
458 | // A web-visitor (HTML and AJAX, but not REST) can use a JWT Cookie |
356 | if (isset($_COOKIE[self::COOKIE_NAME])) { |
459 | if (isset($_COOKIE[self::COOKIE_NAME])) { |
357 | $silent_error = true; |
460 | $silent_error = true; |
358 | $tmp = new OIDplusAuthContentStoreJWT(); |
461 | $tmp = new OIDplusAuthContentStoreJWT(); |
359 | $tmp->loadJWT($_COOKIE[self::COOKIE_NAME]); |
462 | $tmp->loadJWT($_COOKIE[self::COOKIE_NAME]); |
360 | self::jwtSecurityCheck($tmp, self::JWT_GENERATOR_LOGIN | self::JWT_GENERATOR_MANUAL); |
463 | self::jwtSecurityCheck($tmp, self::JWT_GENERATOR_LOGIN | self::JWT_GENERATOR_MANUAL); |
361 | } |
464 | } |
362 | 465 | ||
363 | // AJAX may additionally use GET/POST automated AJAX (in addition to the normal JWT "remember me" Cookie) |
466 | // AJAX may additionally use GET/POST automated AJAX (in addition to the normal web browser login Cookie) |
364 | if (isset($_SERVER['SCRIPT_FILENAME']) && (strtolower(basename($_SERVER['SCRIPT_FILENAME'])) !== 'ajax.php')) { |
467 | if (isset($_SERVER['SCRIPT_FILENAME']) && (strtolower(basename($_SERVER['SCRIPT_FILENAME'])) !== 'ajax.php')) { |
365 | if (isset($_POST[self::COOKIE_NAME])) { |
468 | if (isset($_POST[self::COOKIE_NAME])) { |
366 | $silent_error = false; |
469 | $silent_error = false; |
367 | $tmp = new OIDplusAuthContentStoreJWT(); |
470 | $tmp = new OIDplusAuthContentStoreJWT(); |
368 | $tmp->loadJWT($_POST[self::COOKIE_NAME]); |
471 | $tmp->loadJWT($_POST[self::COOKIE_NAME]); |
Line 405... | Line 508... | ||
405 | if (is_null(self::getActiveProvider())) { |
508 | if (is_null(self::getActiveProvider())) { |
406 | $this->raLogin($email); |
509 | $this->raLogin($email); |
407 | $loginfo = 'into new JWT session'; |
510 | $loginfo = 'into new JWT session'; |
408 | self::$contentProvider = $this; |
511 | self::$contentProvider = $this; |
409 | } else { |
512 | } else { |
410 | $gen = $this->getValue('oidplus_generator',-1); |
513 | $gen = $this->getValue(self::CLAIM_GENERATOR,-1); |
411 | switch ($gen) { |
514 | switch ($gen) { |
412 | case OIDplusAuthContentStoreJWT::JWT_GENERATOR_AJAX : |
515 | case OIDplusAuthContentStoreJWT::JWT_GENERATOR_AJAX : |
413 | case OIDplusAuthContentStoreJWT::JWT_GENERATOR_REST : |
516 | case OIDplusAuthContentStoreJWT::JWT_GENERATOR_REST : |
414 | case OIDplusAuthContentStoreJWT::JWT_GENERATOR_MANUAL : |
517 | case OIDplusAuthContentStoreJWT::JWT_GENERATOR_MANUAL : |
415 | throw new OIDplusException(_L('This kind of JWT token cannot be altered. Therefore you cannot do this action.')); |
518 | throw new OIDplusException(_L('This kind of JWT token cannot be altered. Therefore you cannot do this action.')); |
416 | case OIDplusAuthContentStoreJWT::JWT_GENERATOR_LOGIN : |
519 | case OIDplusAuthContentStoreJWT::JWT_GENERATOR_LOGIN : |
417 | if (!OIDplus::baseConfig()->getValue('JWT_ALLOW_LOGIN_USER', true)) { |
520 | if (!OIDplus::baseConfig()->getValue('JWT_ALLOW_LOGIN_USER', true)) { |
418 | throw new OIDplusException(_L('You cannot add this login credential to your existing "remember me" session. You need to log-out first.')); |
521 | throw new OIDplusException(_L('The administrator has disabled this feature. (Base configuration setting %1).','JWT_ALLOW_LOGIN_USER')); |
419 | } |
522 | } |
420 | break; |
523 | break; |
421 | default: |
524 | default: |
422 | assert(false); // This cannot happen because jwtSecurityCheck will check for unknown generators |
525 | assert(false); // This cannot happen because jwtSecurityCheck will check for unknown generators |
423 | break; |
526 | break; |
Line 436... | Line 539... | ||
436 | if (is_null(self::getActiveProvider())) { |
539 | if (is_null(self::getActiveProvider())) { |
437 | $this->adminLogin(); |
540 | $this->adminLogin(); |
438 | $loginfo = 'into new JWT session'; |
541 | $loginfo = 'into new JWT session'; |
439 | self::$contentProvider = $this; |
542 | self::$contentProvider = $this; |
440 | } else { |
543 | } else { |
441 | $gen = $this->getValue('oidplus_generator',-1); |
544 | $gen = $this->getValue(self::CLAIM_GENERATOR,-1); |
442 | switch ($gen) { |
545 | switch ($gen) { |
443 | case OIDplusAuthContentStoreJWT::JWT_GENERATOR_AJAX : |
546 | case OIDplusAuthContentStoreJWT::JWT_GENERATOR_AJAX : |
444 | case OIDplusAuthContentStoreJWT::JWT_GENERATOR_REST : |
547 | case OIDplusAuthContentStoreJWT::JWT_GENERATOR_REST : |
445 | case OIDplusAuthContentStoreJWT::JWT_GENERATOR_MANUAL : |
548 | case OIDplusAuthContentStoreJWT::JWT_GENERATOR_MANUAL : |
446 | throw new OIDplusException(_L('This kind of JWT token cannot be altered. Therefore you cannot do this action.')); |
549 | throw new OIDplusException(_L('This kind of JWT token cannot be altered. Therefore you cannot do this action.')); |
447 | case OIDplusAuthContentStoreJWT::JWT_GENERATOR_LOGIN : |
550 | case OIDplusAuthContentStoreJWT::JWT_GENERATOR_LOGIN : |
448 | if (!OIDplus::baseConfig()->getValue('JWT_ALLOW_LOGIN_ADMIN', true)) { |
551 | if (!OIDplus::baseConfig()->getValue('JWT_ALLOW_LOGIN_ADMIN', true)) { |
449 | throw new OIDplusException(_L('You cannot add this login credential to your existing "remember me" session. You need to log-out first.')); |
552 | throw new OIDplusException(_L('The administrator has disabled this feature. (Base configuration setting %1).','JWT_ALLOW_LOGIN_ADMIN')); |
450 | } |
553 | } |
451 | break; |
554 | break; |
452 | default: |
555 | default: |
453 | assert(false); // This cannot happen because jwtSecurityCheck will check for unknown generators |
556 | assert(false); // This cannot happen because jwtSecurityCheck will check for unknown generators |
454 | break; |
557 | break; |
Line 484... | Line 587... | ||
484 | * @return string |
587 | * @return string |
485 | * @throws OIDplusException |
588 | * @throws OIDplusException |
486 | */ |
589 | */ |
487 | public function getJWTToken(): string { |
590 | public function getJWTToken(): string { |
488 | $payload = $this->content; |
591 | $payload = $this->content; |
489 | $payload["oidplus_ssh"] = self::getSsh(); // SSH = Server Secret Hash |
592 | $payload[self::CLAIM_SSH] = self::getSsh(); // SSH = Server Secret Hash |
490 | $payload["iss"] = OIDplus::getEditionInfo()['jwtaud']; |
593 | $payload["iss"] = OIDplus::getEditionInfo()['jwtaud']; |
491 | $payload["aud"] = OIDplus::getEditionInfo()['jwtaud']; |
594 | $payload["aud"] = OIDplus::getEditionInfo()['jwtaud']; |
492 | $payload["jti"] = gen_uuid(); |
595 | $payload["jti"] = gen_uuid(); |
493 | $payload["iat"] = time(); |
596 | $payload["iat"] = time(); |
494 | 597 |