]> git.mxchange.org Git - friendica.git/blobdiff - src/Security/Authentication.php
An empty user id does not have children
[friendica.git] / src / Security / Authentication.php
index 089035bb7f1fa803da61e0db30dc8a5f7dbabe07..ce101477e0a2ee043764ea18b70ac98c8d0ad970 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * @copyright Copyright (C) 2020, Friendica
+ * @copyright Copyright (C) 2010-2021, the Friendica project
  *
  * @license GNU AGPL version 3 or any later version
  *
@@ -33,12 +33,13 @@ use Friendica\Database\DBA;
 use Friendica\DI;
 use Friendica\Model\User;
 use Friendica\Network\HTTPException;
-use Friendica\Repository\TwoFactor\TrustedBrowser;
+use Friendica\Security\TwoFactor\Repository\TrustedBrowser;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Network;
 use Friendica\Util\Strings;
 use LightOpenID;
 use Friendica\Core\L10n;
+use Friendica\Core\Logger;
 use Psr\Log\LoggerInterface;
 
 /**
@@ -239,34 +240,12 @@ class Authentication
        {
                $record = null;
 
-               $addon_auth = [
-                       'username'      => $username,
-                       'password'      => $password,
-                       'authenticated' => 0,
-                       'user_record'   => null
-               ];
-
-               /*
-                * An addon indicates successful login by setting 'authenticated' to non-zero value and returning a user record
-                * Addons should never set 'authenticated' except to indicate success - as hooks may be chained
-                * and later addons should not interfere with an earlier one that succeeded.
-                */
-               Hook::callAll('authenticate', $addon_auth);
-
                try {
-                       if ($addon_auth['authenticated']) {
-                               $record = $addon_auth['user_record'];
-
-                               if (empty($record)) {
-                                       throw new Exception($this->l10n->t('Login failed.'));
-                               }
-                       } else {
-                               $record = $this->dba->selectFirst(
-                                       'user',
-                                       [],
-                                       ['uid' => User::getIdFromPasswordAuthentication($username, $password)]
-                               );
-                       }
+                       $record = $this->dba->selectFirst(
+                               'user',
+                               [],
+                               ['uid' => User::getIdFromPasswordAuthentication($username, $password)]
+                       );
                } catch (Exception $e) {
                        $this->logger->warning('authenticate: failed login attempt', ['action' => 'login', 'username' => Strings::escapeTags($username), 'ip' => $_SERVER['REMOTE_ADDR']]);
                        notice($this->l10n->t('Login failed. Please check your credentials.'));
@@ -363,8 +342,10 @@ class Authentication
                        $this->dba->update('user', ['login_date' => DateTimeFormat::utcNow()], ['uid' => $user_record['uid']]);
 
                        // Set the login date for all identities of the user
-                       $this->dba->update('user', ['login_date' => DateTimeFormat::utcNow()],
-                               ['parent-uid' => $masterUid, 'account_removed' => false]);
+                       if (!empty($masterUid)) {
+                               $this->dba->update('user', ['login_date' => DateTimeFormat::utcNow()],
+                                       ['parent-uid' => $masterUid, 'account_removed' => false]);
+                       }
                }
 
                if ($login_initial) {
@@ -427,11 +408,38 @@ class Authentication
                        return;
                }
 
-               // Case 1: 2FA session present and valid: return
+               // Case 1a: 2FA session already present: return
                if ($this->session->get('2fa')) {
                        return;
                }
 
+               // Case 1b: Check for trusted browser
+               if ($this->cookie->get('trusted')) {
+                       // Retrieve a trusted_browser model based on cookie hash
+                       $trustedBrowserRepository = new TrustedBrowser($this->dba, $this->logger);
+                       try {
+                               $trustedBrowser = $trustedBrowserRepository->selectOneByHash($this->cookie->get('trusted'));
+                               // Verify record ownership
+                               if ($trustedBrowser->uid === $uid) {
+                                       // Update last_used date
+                                       $trustedBrowser->recordUse();
+
+                                       // Save it to the database
+                                       $trustedBrowserRepository->save($trustedBrowser);
+
+                                       // Set 2fa session key and return
+                                       $this->session->set('2fa', true);
+
+                                       return;
+                               } else {
+                                       // Invalid trusted cookie value, removing it
+                                       $this->cookie->unset('trusted');
+                               }
+                       } catch (\Throwable $e) {
+                               // Local trusted browser record was probably removed by the user, we carry on with 2FA
+                       }
+               }
+
                // Case 2: No valid 2FA session: redirect to code verification page
                if ($this->mode->isAjax()) {
                        throw new HTTPException\ForbiddenException();