From e1060d230de5d5448db6aa2d8a94e6bf69942407 Mon Sep 17 00:00:00 2001 From: meirzamoodle Date: Mon, 3 Mar 2025 21:16:28 +0700 Subject: [PATCH] MDL-65027 core_auth: Implement reCaptcha on forgot password page --- admin/settings/plugins.php | 9 +++++++++ lang/en/auth.php | 2 ++ lib/authlib.php | 10 ++++++++++ login/forgot_password_form.php | 28 ++++++++++++++++++++++++---- 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/admin/settings/plugins.php b/admin/settings/plugins.php index dd413bf7145..60f43d86f50 100644 --- a/admin/settings/plugins.php +++ b/admin/settings/plugins.php @@ -157,6 +157,15 @@ if ($hassiteconfig) { ], )); + + // Forgot password ReCaptcha. + $temp->add(new admin_setting_configcheckbox( + 'enableforgotpasswordrecaptcha', + new lang_string('auth_forgotpasswordrecaptcha', 'auth'), + new lang_string('auth_forgotpasswordrecaptcha_desc', 'auth'), + 0, + )); + $setting = new admin_setting_configtext('recaptchapublickey', new lang_string('recaptchapublickey', 'admin'), new lang_string('configrecaptchapublickey', 'admin'), '', PARAM_NOTAGS); $setting->set_force_ltr(true); $temp->add($setting); diff --git a/lang/en/auth.php b/lang/en/auth.php index aab19c9add5..463a2bb8bb7 100644 --- a/lang/en/auth.php +++ b/lang/en/auth.php @@ -34,6 +34,8 @@ $string['auth_fieldlock_expl'] = '

Lock value: If enabled, users will not be a $string['auth_fieldlocks'] = 'Lock user fields'; $string['auth_fieldlocks_help'] = '

You can lock user data fields. This is useful for sites where the user data is maintained by the administrators manually by editing user records or uploading using the \'Upload users\' facility. If you are locking fields that are required by Moodle, make sure that you provide that data when creating user accounts or the accounts will be unusable.

Consider setting the lock mode to \'Unlocked if empty\' to avoid this problem.

'; $string['auth_fieldmapping'] = 'Data mapping ({$a})'; +$string['auth_forgotpasswordrecaptcha'] = 'Enable reCAPTCHA for forgot password'; +$string['auth_forgotpasswordrecaptcha_desc'] = 'Add a visual/audio confirmation form element to the forgot password page. This reduces the risk of unwarranted forgotten password attempts. See Google reCAPTCHA for more details.'; $string['auth_changepasswordhelp'] = 'Change password help'; $string['auth_changepasswordhelp_expl'] = 'Display lost password help to users who have lost their {$a} password. This will be displayed either as well as or instead of the Change Password URL or Internal Moodle password change.'; $string['auth_changepasswordurl'] = 'Change password URL'; diff --git a/lib/authlib.php b/lib/authlib.php index eaf7983f903..ebe2866ed49 100644 --- a/lib/authlib.php +++ b/lib/authlib.php @@ -1115,6 +1115,16 @@ function login_captcha_enabled(): bool { return !empty($CFG->recaptchapublickey) && !empty($CFG->recaptchaprivatekey) && $CFG->enableloginrecaptcha == true; } +/** + * Checks if the captcha is enabled for the forgot password feature. + * + * @return bool True if captcha is enabled, false otherwise. + */ +function forgotpassword_captcha_enabled(): bool { + global $CFG; + return !empty($CFG->recaptchapublickey) && !empty($CFG->recaptchaprivatekey) && $CFG->enableforgotpasswordrecaptcha == true; +} + /** * Check the submitted captcha is valid or not. * diff --git a/login/forgot_password_form.php b/login/forgot_password_form.php index 4ad2447c2b4..502a8b1e03f 100644 --- a/login/forgot_password_form.php +++ b/login/forgot_password_form.php @@ -56,17 +56,25 @@ class login_forgot_password_form extends moodleform { $mform->addElement('text', 'username', get_string('username'), 'size="20"' . $purpose); $mform->setType('username', PARAM_RAW); - $submitlabel = get_string('search'); - $mform->addElement('submit', 'submitbuttonusername', $submitlabel); - $mform->addElement('header', 'searchbyemail', get_string('searchbyemail'), ''); $purpose = user_edit_map_field_purpose($USER->id, 'email'); $mform->addElement('text', 'email', get_string('email'), 'maxlength="100" size="30"' . $purpose); $mform->setType('email', PARAM_RAW_TRIMMED); + // Avoid the user to fill both fields. + $mform->disabledIf('email', 'username', 'neq', ''); + $mform->disabledIf('username', 'email', 'neq', ''); + + $mform->addElement('html', '
'); + + // Adds a reCAPTCHA element to the forgot password form if the forgot password captcha is enabled. + if (forgotpassword_captcha_enabled()) { + $mform->addElement('recaptcha', 'recaptcha_element', ''); + } + $submitlabel = get_string('search'); - $mform->addElement('submit', 'submitbuttonemail', $submitlabel); + $mform->addElement('submit', 'submit', $submitlabel); } /** @@ -79,6 +87,18 @@ class login_forgot_password_form extends moodleform { $errors = parent::validation($data, $files); + if (forgotpassword_captcha_enabled()) { + $recaptchaelement = $this->_form->getElement('recaptcha_element'); + if (!empty($this->_form->_submitValues['g-recaptcha-response'])) { + $response = $this->_form->_submitValues['g-recaptcha-response']; + if (!$recaptchaelement->verify($response)) { + $errors['recaptcha_element'] = get_string('incorrectpleasetryagain', 'auth'); + } + } else { + $errors['recaptcha_element'] = get_string('missingrecaptchachallengefield'); + } + } + // Extend validation for any form extensions from plugins. $errors = array_merge($errors, core_login_validate_extend_forgot_password_form($data));