diff --git a/CHANGELOG.md b/CHANGELOG.md index bd230d5..a360aac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,15 @@ +# v3.7.6 +## 06/29/2023 + +1. [](#bugfix) + * Don't save an empty user file on password reset of non-existing user + # v3.7.5 ## 06/14/2023 1. [](#bugfix) * Sanitized `email` during the "forgot password" process to protect against XSS attacks - * Fixed an account enumeration vulneratiblity in forgot password [#293](https://github.com/getgrav/grav-plugin-login/pull/293) + * Fixed an account enumeration vulnerability in forgot password [#293](https://github.com/getgrav/grav-plugin-login/pull/293) # v3.7.4 ## 05/09/2023 diff --git a/blueprints.yaml b/blueprints.yaml index bd7b61b..ce93d34 100644 --- a/blueprints.yaml +++ b/blueprints.yaml @@ -1,7 +1,7 @@ name: Login slug: login type: plugin -version: 3.7.5 +version: 3.7.6 testing: false description: Enables user authentication and login screen. icon: sign-in diff --git a/classes/Controller.php b/classes/Controller.php index 9421cdd..ed006d7 100644 --- a/classes/Controller.php +++ b/classes/Controller.php @@ -347,61 +347,66 @@ protected function taskForgot() $config = $this->grav['config']; $data = $this->post; + /** @var Language $language */ + $language = $this->grav['language']; + $messages = $this->grav['messages']; + /** @var UserCollectionInterface $users */ $users = $this->grav['accounts']; - $email = $data['email'] ?? ''; // Sanitize $email $email = htmlspecialchars(strip_tags($email), ENT_QUOTES, 'UTF-8'); - $user = !empty($email) ? $users->find($email, ['email']) : null; - - /** @var Language $language */ - $language = $this->grav['language']; - $messages = $this->grav['messages']; + // Find user if they exist + $user = $users->find($email, ['email']); - if (!isset($this->grav['Email'])) { - $messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error'); - $this->setRedirect($this->login->getRoute('forgot') ?? '/'); + if ($user->exists()) { + if (!isset($this->grav['Email'])) { + $messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error'); + $this->setRedirect($this->login->getRoute('forgot') ?? '/'); - return true; - } + return true; + } - $from = $config->get('plugins.email.from'); + $from = $config->get('plugins.email.from'); - if (empty($from)) { - $messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error'); - $this->setRedirect($this->login->getRoute('forgot') ?? '/'); + if (empty($from)) { + $messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error'); + $this->setRedirect($this->login->getRoute('forgot') ?? '/'); - return true; - } + return true; + } - $userKey = $user->username; - $rateLimiter = $this->login->getRateLimiter('pw_resets'); - $rateLimiter->registerRateLimitedAction($userKey); + $userKey = $user->username; + $rateLimiter = $this->login->getRateLimiter('pw_resets'); + $rateLimiter->registerRateLimitedAction($userKey); - if ($rateLimiter->isRateLimited($userKey)) { - $messages->add($language->translate(['PLUGIN_LOGIN.FORGOT_CANNOT_RESET_IT_IS_BLOCKED', $email, $rateLimiter->getInterval()]), 'error'); - $this->setRedirect($this->login->getRoute('login') ?? '/'); + if ($rateLimiter->isRateLimited($userKey)) { + $messages->add($language->translate(['PLUGIN_LOGIN.FORGOT_CANNOT_RESET_IT_IS_BLOCKED', $email, $rateLimiter->getInterval()]), 'error'); + $this->setRedirect($this->login->getRoute('login') ?? '/'); - return true; - } + return true; + } - $token = md5(uniqid((string)mt_rand(), true)); - $expire = time() + 604800; // next week + $token = md5(uniqid((string)mt_rand(), true)); + $expire = time() + 604800; // next week - $user->reset = $token . '::' . $expire; - $user->save(); + $user->reset = $token . '::' . $expire; + $user->save(); - try { - Email::sendResetPasswordEmail($user); + try { + Email::sendResetPasswordEmail($user); + $messages->add($language->translate('PLUGIN_LOGIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL'), 'info'); + } catch (\Exception $e) { + $messages->add($language->translate('PLUGIN_LOGIN.FORGOT_FAILED_TO_EMAIL'), 'error'); + } + } else { $messages->add($language->translate('PLUGIN_LOGIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL'), 'info'); - } catch (\Exception $e) { - $messages->add($language->translate('PLUGIN_LOGIN.FORGOT_FAILED_TO_EMAIL'), 'error'); } + $this->setRedirect($this->login->getRoute('login') ?? '/'); return true;