File modules/cms/auth/RememberAuth.class.php
Last commit: Fri Apr 15 14:51:22 2022 +0200 dankert Refactoring: User,Config and Database info is now stored in the Request, because so there is no session required for clients which are using Basic Authorization.
1 <?php 2 3 namespace cms\auth; 4 5 use cms\action\Action; 6 use cms\base\Configuration; 7 use cms\base\DB; 8 use cms\base\Startup; 9 use database\Database; 10 use cms\model\User; 11 use logger\Logger; 12 use util\Cookie; 13 use security\Password; 14 use \util\exception\ObjectNotFoundException; 15 use util\Request; 16 use util\Session; 17 use util\text\TextMessage; 18 19 /** 20 * Authentifizierung mit einem Login-Token. 21 * 22 * @author dankert 23 */ 24 class RememberAuth implements Auth 25 { 26 /** 27 * @return null 28 */ 29 public function username() 30 { 31 // Ermittelt den Benutzernamen aus den Login-Cookies. 32 if ( Cookie::has(Action::COOKIE_TOKEN) && 33 Cookie::has(Action::COOKIE_DB_ID) ) { 34 try { 35 list($selector, $token) = array_pad(explode('.', Cookie::get(Action::COOKIE_TOKEN)), 2, ''); 36 $dbid = Cookie::get( Action::COOKIE_DB_ID ); 37 38 $allDbConfig = Configuration::subset('database'); 39 40 if (!$allDbConfig->has($dbid)) { 41 42 Logger::warn( TextMessage::create('Unknown DB-Id ${0}, no login with token possible',[$dbid]) ); 43 return null; 44 } 45 46 $dbConfig = $allDbConfig->subset($dbid); 47 48 if (! $dbConfig->is('enabled',true)) { 49 50 Logger::warn( TextMessage::create('DB-Id ${0} is disabled, no login with login token possible',[$dbid]) ); 51 return null; 52 } 53 54 $key = 'read'; // Only reading in database. 55 56 $db = new Database($dbConfig->merge( $dbConfig->subset($key) )->getConfig()); 57 $db->id = $dbid; 58 $db->start(); 59 60 $stmt = $db->sql(<<<SQL 61 SELECT userid,{{user}}.name as username,token,token_algo FROM {{auth}} 62 LEFT JOIN {{user}} ON {{auth}}.userid = {{user}}.id 63 WHERE selector = {selector} AND expires > {now} 64 SQL 65 ); 66 $stmt->setString('selector', $selector); 67 $stmt->setInt ('now' , Startup::getStartTime() ); 68 69 $auth = $stmt->getRow(); 70 $db->disconnect(); 71 72 73 if ($auth) { 74 $this->makeDBWritable( $dbid ); // FIXME: This is a hack, how to do this better? 75 // serial was found. 76 $username = $auth['username']; 77 $userid = $auth['userid' ]; 78 $user = new User( $userid ); 79 80 if (Password::check($token, $auth['token'], $auth['token_algo'])) { 81 Cookie::set(Action::COOKIE_TOKEN ,$user->createNewLoginTokenForSerial($selector) ); 82 DB::get()->commit(); 83 return $username; 84 } 85 else { 86 // serial match but token mismatched. 87 // this means, the token was used on another device before, probably stolen. 88 Logger::warn( TextMessage::create('Possible breakin-attempt detected for user ${0}',[$username])); 89 $user->deleteAllLoginTokens(); // Disable all token logins for this user. 90 Cookie::set(Action::COOKIE_TOKEN ); // Delete token cookie 91 92 // we must not reset the password here, because the thief might not have it. 93 94 return null; 95 } 96 } else { 97 // The serial is not found, maybe expired. 98 // There is nothing we should do here. 99 } 100 101 102 } catch (ObjectNotFoundException $e) { 103 // Benutzer nicht gefunden. 104 } 105 } 106 107 return null; 108 } 109 110 111 /** 112 * Ueberpruefen des Kennwortes ist über den Cookie nicht möglich. 113 */ 114 public function login($user, $password, $token) 115 { 116 return Auth::STATUS_FAILED; 117 } 118 119 protected function makeDBWritable( $dbid ) { 120 121 $oldDB = Request::getDatabase(); 122 if ( $oldDB ) { 123 $oldDB->rollback(); 124 $oldDB->disconnect(); 125 } 126 127 $dbConfig = Configuration::subset(['database',$dbid]); 128 129 $key = 'write'; 130 $writableDB = new Database($dbConfig->merge( $dbConfig->subset($key) )->getConfig()); 131 $writableDB->id = $dbid; 132 $writableDB->start(); 133 134 Request::setDatabase( $writableDB ); 135 } 136 }
Downloadmodules/cms/auth/RememberAuth.class.php
History Fri, 15 Apr 2022 14:51:22 +0200 dankert Refactoring: User,Config and Database info is now stored in the Request, because so there is no session required for clients which are using Basic Authorization. Mon, 30 Nov 2020 09:57:36 +0100 Jan Dankert Fix: aborting transaction before changing the database connection; Refactoring: Cleanup databases Sun, 29 Nov 2020 21:46:57 +0100 Jan Dankert Auth modules should only use the Auth::STATUS_* constants as return value. Thu, 19 Nov 2020 11:23:17 +0100 Jan Dankert Fix: DB connections must be enabled. Thu, 19 Nov 2020 00:45:44 +0100 Jan Dankert Security fix: We must update the login token on every login; Administrators are able to see the login tokens of users. Wed, 18 Nov 2020 20:42:57 +0100 Jan Dankert Getting/Setting cookies with constants, this is more safe. Mon, 16 Nov 2020 13:21:57 +0100 Jan Dankert Code cleanup: Externalize calling the auth modules. Sun, 1 Nov 2020 00:36:50 +0100 Jan Dankert Refactoring: Only using the configuration object. Mon, 26 Oct 2020 22:21:42 +0100 Jan Dankert Refactoring: Using TextMessage for creating Messages with user content. Tue, 29 Sep 2020 22:17:11 +0200 Jan Dankert Refactoring: Do not use global constants. Sat, 26 Sep 2020 04:26:55 +0200 Jan Dankert Refactoring: read configuration values with a class. Tue, 18 Aug 2020 23:27:37 +0200 Jan Dankert Security: Sanitize user input while logging (no logfile injection with potentially dangerous data) Sun, 23 Feb 2020 04:49:34 +0100 Jan Dankert Refactoring with Namespaces for the cms modules, part 2. Sun, 23 Feb 2020 04:01:30 +0100 Jan Dankert Refactoring with Namespaces for the cms modules, part 1: moving.