X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FSecurity%2FAuthentication.php;h=c6a84036728c652384872c69c1d4c61c4592486a;hb=e0fa557f18d544d81c37fa8c2554ec5240a64d4b;hp=a0b9270262c4e6c6bd3760dad7f2140d7476e16f;hpb=fc283ab92858238a5a55f24b1d1650bb72068b7d;p=friendica.git diff --git a/src/Security/Authentication.php b/src/Security/Authentication.php index a0b9270262..c6a8403672 100644 --- a/src/Security/Authentication.php +++ b/src/Security/Authentication.php @@ -1,6 +1,6 @@ config = $config; - $this->mode = $mode; - $this->baseUrl = $baseUrl; - $this->l10n = $l10n; - $this->dba = $dba; - $this->logger = $logger; - $this->cookie = $cookie; - $this->session = $session; - $this->pConfig = $pConfig; + $this->config = $config; + $this->mode = $mode; + $this->baseUrl = $baseUrl; + $this->l10n = $l10n; + $this->dba = $dba; + $this->logger = $logger; + $this->cookie = $cookie; + $this->session = $session; + $this->pConfig = $pConfig; + $this->remoteAddress = $request->getRemoteAddress(); } /** @@ -129,7 +145,7 @@ class Authentication // Renew the cookie $this->cookie->send(); - // Do the authentification if not done by now + // Do the authentication if not done by now if (!$this->session->get('authenticated')) { $this->setForUser($a, $user); @@ -152,10 +168,11 @@ class Authentication // already logged in user returning $check = $this->config->get('system', 'paranoia'); // extra paranoia - if the IP changed, log them out - if ($check && ($this->session->get('addr') != $_SERVER['REMOTE_ADDR'])) { + if ($check && ($this->session->get('addr') != $this->remoteAddress)) { $this->logger->notice('Session address changed. Paranoid setting in effect, blocking session. ', [ - 'addr' => $this->session->get('addr'), - 'remote_addr' => $_SERVER['REMOTE_ADDR']] + 'addr' => $this->session->get('addr'), + 'remote_addr' => $this->remoteAddress + ] ); $this->session->clear(); $this->baseUrl->redirect(); @@ -207,7 +224,7 @@ class Authentication // if it's an email address or doesn't resolve to a URL, fail. if ($noid || strpos($openid_url, '@') || !Network::isUrlValid($openid_url)) { - notice($this->l10n->t('Login failed.')); + DI::sysmsg()->addNotice($this->l10n->t('Login failed.')); $this->baseUrl->redirect(); } @@ -221,22 +238,26 @@ class Authentication $openid->optional = ['namePerson/friendly', 'contact/email', 'namePerson', 'namePerson/first', 'media/image/aspect11', 'media/image/default']; System::externalRedirect($openid->authUrl()); } catch (Exception $e) { - notice($this->l10n->t('We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID.') . '

' . $this->l10n->t('The error message was:') . ' ' . $e->getMessage()); + DI::sysmsg()->addNotice($this->l10n->t('We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID.') . '

' . $this->l10n->t('The error message was:') . ' ' . $e->getMessage()); } } /** * Attempts to authenticate using login/password * - * @param App $a The Friendica Application context - * @param string $username User name - * @param string $password Clear password - * @param bool $remember Whether to set the session remember flag + * @param App $a The Friendica Application context + * @param string $username + * @param string $password Clear password + * @param bool $remember Whether to set the session remember flag + * @param string $return_path The relative path to redirect the user to after authentication * - * @throws HttpException\InternalServerErrorException In case of Friendica internal exceptions - * @throws Exception A general Exception (like SQL Grammar exceptions) + * @throws HTTPException\ForbiddenException + * @throws HTTPException\FoundException + * @throws HTTPException\InternalServerErrorException In case of Friendica internal exceptions + * @throws HTTPException\MovedPermanentlyException + * @throws HTTPException\TemporaryRedirectException */ - public function withPassword(App $a, string $username, string $password, bool $remember) + public function withPassword(App $a, string $username, string $password, bool $remember, string $return_path = '') { $record = null; @@ -247,13 +268,17 @@ class Authentication ['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.')); + $this->logger->warning('authenticate: failed login attempt', ['action' => 'login', 'username' => $username, 'ip' => $this->remoteAddress]); + DI::sysmsg()->addNotice($this->l10n->t('Login failed. Please check your credentials.')); $this->baseUrl->redirect(); } if (!$remember) { + $trusted = $this->cookie->get('2fa_cookie_hash') ?? null; $this->cookie->clear(); + if ($trusted) { + $this->cookie->set('2fa_cookie_hash', $trusted); + } } // if we haven't failed up this point, log them in. @@ -267,10 +292,14 @@ class Authentication $this->dba->update('user', ['openid' => $openid_identity, 'openidserver' => $openid_server], ['uid' => $record['uid']]); } - $this->setForUser($a, $record, true, true); + /** + * @see User::getPasswordRegExp() + */ + if (PASSWORD_DEFAULT === PASSWORD_BCRYPT && strlen($password) > 72) { + $return_path = '/security/password_too_long?' . http_build_query(['return_path' => $return_path]); + } - $return_path = $this->session->get('return_path', ''); - $this->session->remove('return_path'); + $this->setForUser($a, $record, true, true); $this->baseUrl->redirect($return_path); } @@ -284,8 +313,13 @@ class Authentication * @param bool $interactive * @param bool $login_refresh * + * @throws HTTPException\FoundException + * @throws HTTPException\MovedPermanentlyException + * @throws HTTPException\TemporaryRedirectException + * @throws HTTPException\ForbiddenException + * @throws HTTPException\InternalServerErrorException In case of Friendica specific exceptions - * @throws Exception In case of general Exceptions (like SQL Grammar exceptions) + * */ public function setForUser(App $a, array $user_record, bool $login_initial = false, bool $interactive = false, bool $login_refresh = false) { @@ -297,16 +331,16 @@ class Authentication 'page_flags' => $user_record['page-flags'], 'my_url' => $this->baseUrl->get() . '/profile/' . $user_record['nickname'], 'my_address' => $user_record['nickname'] . '@' . substr($this->baseUrl->get(), strpos($this->baseUrl->get(), '://') + 3), - 'addr' => ($_SERVER['REMOTE_ADDR'] ?? '') ?: '0.0.0.0' + 'addr' => $this->remoteAddress, + 'nickname' => $user_record['nickname'], ]); - Session::setVisitorsContacts(); + $this->session->setVisitorsContacts(); $member_since = strtotime($user_record['register_date']); $this->session->set('new_member', time() < ($member_since + (60 * 60 * 24 * 14))); if (strlen($user_record['timezone'])) { - date_default_timezone_set($user_record['timezone']); $a->setTimeZone($user_record['timezone']); } @@ -316,14 +350,19 @@ class Authentication $this->session->set('cid', $contact['id']); } - header('X-Account-Management-Status: active; name="' . $user_record['username'] . '"; id="' . $user_record['nickname'] . '"'); + $this->setXAccMgmtStatusHeader($user_record); if ($login_initial || $login_refresh) { - $this->dba->update('user', ['login_date' => DateTimeFormat::utcNow()], ['uid' => $user_record['uid']]); + $this->dba->update('user', ['last-activity' => DateTimeFormat::utcNow('Y-m-d'), '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()], + $this->dba->update('user', ['last-activity' => DateTimeFormat::utcNow('Y-m-d'), 'login_date' => DateTimeFormat::utcNow()], ['parent-uid' => $user_record['uid'], 'account_removed' => false]); + + // Regularly update suggestions + if (Contact\Relation::areSuggestionsOutdated($user_record['uid'])) { + Worker::add(Worker::PRIORITY_MEDIUM, 'UpdateSuggestions', $user_record['uid']); + } } if ($login_initial) { @@ -347,22 +386,14 @@ class Authentication if ($interactive) { if ($user_record['login_date'] <= DBA::NULL_DATETIME) { - info($this->l10n->t('Welcome %s', $user_record['username'])); - info($this->l10n->t('Please upload a profile photo.')); + DI::sysmsg()->addInfo($this->l10n->t('Welcome %s', $user_record['username'])); + DI::sysmsg()->addInfo($this->l10n->t('Please upload a profile photo.')); $this->baseUrl->redirect('settings/profile/photo/new'); } } - $a->setUserId($user_record['uid']); - $a->setNickname($user_record['nickname']); - $a->user = $user_record; - if ($login_initial) { Hook::callAll('logged_in', $user_record); - - if (DI::module()->getName() !== 'home' && $this->session->exists('return_path')) { - $this->baseUrl->redirect($this->session->get('return_path')); - } } } @@ -393,11 +424,11 @@ class Authentication } // Case 1b: Check for trusted browser - if ($this->cookie->get('trusted')) { + if ($this->cookie->get('2fa_cookie_hash')) { // Retrieve a trusted_browser model based on cookie hash $trustedBrowserRepository = new TrustedBrowser($this->dba, $this->logger); try { - $trustedBrowser = $trustedBrowserRepository->selectOneByHash($this->cookie->get('trusted')); + $trustedBrowser = $trustedBrowserRepository->selectOneByHash($this->cookie->get('2fa_cookie_hash')); // Verify record ownership if ($trustedBrowser->uid === $uid) { // Update last_used date @@ -406,10 +437,13 @@ class Authentication // Save it to the database $trustedBrowserRepository->save($trustedBrowser); - // Set 2fa session key and return - $this->session->set('2fa', true); + // Only use this entry, if its really trusted, otherwise just update the record and proceed + if ($trustedBrowser->trusted) { + // Set 2fa session key and return + $this->session->set('2fa', true); - return; + return; + } } else { // Invalid trusted cookie value, removing it $this->cookie->unset('trusted');