[TikiWiki-commits] [Git][tikiwiki/tiki][master] [FIX] Fix password change for users required to change password at next login
Benoit Grégoire (@benoitg) via TikiWiki-cvs <[email protected]>
| Newsgroups | gmane.comp.cms.tiki.cvs |
|---|---|
| Message-ID | <697128a1bdb8a_2c182e00798cb@gitlab-sidekiq-low-urgency-cpu-bound-v2-867f88b8bf-w64vb.mail> |
Benoit Grégoire pushed to branch master at Tiki Wiki CMS Groupware / Tiki
Commits:
7cc02fcd by Espoir Baraka at 2026-01-21T19:18:58+00:00
[FIX] Fix password change for users required to change password at next login
---
* [FIX] Fix password change for users required to change password at next login
See merge request tikiwiki/tiki!9207
- - - - -
1 changed file:
- tiki-change_password.php
Changes:
=====================================
tiki-change_password.php
=====================================
@@ -65,102 +65,139 @@ if (isset($_REQUEST["change"])) {
}
}
- // If this is a new user validation, we do not check the token
- if (! isset($_REQUEST["new_user_validation"]) && $_REQUEST["new_user_validation"] !== 'y') {
- // Check if the secure token is valid
- if (empty($secure_token)) {
- Feedback::errorAndDie(tra("Missing reset token."), \Laminas\Http\Response::STATUS_CODE_400);
+ // Verify authentication (oldpass, actpass, or token)
+ $is_authenticated = false;
+ $authenticated_oldpass = null;
+ $can_change_password = false;
+ $is_new_user_validation = isset($_REQUEST["new_user_validation"]) && $_REQUEST["new_user_validation"] === 'y';
+ $pass_confirm = $userlib->getOne('select `pass_confirm` from `users_users` where binary `login`=?', [$user]);
+ $must_change_password = ($pass_confirm === 0 || $pass_confirm === null);
+
+ // Method 1: Activation code
+ if (! empty($_REQUEST['actpass'])) {
+ $authenticated_oldpass = $userlib->activate_password($_REQUEST['user'], $_REQUEST['actpass']);
+ if (! empty($authenticated_oldpass)) {
+ $is_authenticated = true;
+ $can_change_password = true;
+ } else {
+ Feedback::error(tra('Invalid username or activation code. Maybe this code has already been used.'));
}
-
- $passwordResetLib = new \Tiki\Lib\Auth\PasswordResetLib();
- $token_info = $passwordResetLib->validatePasswordResetToken($user, $secure_token);
-
- if (! $token_info) {
- Feedback::errorAndDie(tra("Invalid or expired reset token."), \Laminas\Http\Response::STATUS_CODE_403);
+ } elseif (! empty($secure_token)) {
+ // Method 2: Reset token
+ // Check if reset token is allowed for users who must change password
+ if ($must_change_password) {
+ Feedback::error(tra("Reset token cannot be used when password change is required. Please use your old password."));
+ } else {
+ // Reset token is allowed for regular password resets (not new user validation)
+ $passwordResetLib = new \Tiki\Lib\Auth\PasswordResetLib();
+ $token_info = $passwordResetLib->validatePasswordResetToken($user, $secure_token);
+ if (! $token_info) {
+ Feedback::error(tra("Invalid or expired reset token."));
+ } else {
+ // Token will be marked as used after successful password change
+ $is_authenticated = true;
+ $can_change_password = true;
+ }
}
-
- // Mark the token as used to prevent reuse
- $passwordResetLib->markPasswordResetTokenUsed($user, $secure_token);
- }
-
- // Check that pass and passAgain match, otherwise display error and exit
- if ($_REQUEST["pass"] != $_REQUEST["passAgain"]) {
- Feedback::errorAndDie(tra("The passwords do not match"), \Laminas\Http\Response::STATUS_CODE_400);
- }
-
- // Check that new password is different from old password, otherwise display error and exit
- if ($_REQUEST["pass"] == $_REQUEST["oldpass"]) {
- Feedback::errorAndDie(tra("You can not use the same password again"), \Laminas\Http\Response::STATUS_CODE_400);
- }
-
- $polerr = $userlib->check_password_policy($_REQUEST["pass"]);
- if (strlen($polerr) > 0) {
- Feedback::errorAndDie($polerr, \Laminas\Http\Response::STATUS_CODE_400);
+ } elseif (! empty($_REQUEST['oldpass'])) {
+ // Method 3: Old password
+ list($isvalid, $validated_username, $error) = $userlib->validate_user($user, $_REQUEST["oldpass"]);
+ if ($isvalid) {
+ $is_authenticated = true;
+ $can_change_password = true;
+ $authenticated_oldpass = $_REQUEST['oldpass'];
+ } else {
+ Feedback::error(tra("Invalid old password"));
+ }
+ } elseif ($is_new_user_validation) {
+ // Method 4: New user validation (no authentication required - legitimate exception)
+ $can_change_password = true;
+ } elseif ($must_change_password) {
+ // Method 5: User must change password - old password is required
+ Feedback::error(tra("Old password is required to change your password."));
+ } else {
+ // No authentication method was attempted
+ Feedback::error(tra("Authentication required. Please provide your old password, activation code, or reset token."));
}
- if (empty($_REQUEST['oldpass']) && ! empty($_REQUEST['actpass'])) {
- $_REQUEST['oldpass'] = $userlib->activate_password($_REQUEST['user'], $_REQUEST['actpass']);
- if (empty($_REQUEST['oldpass'])) {
- Feedback::errorAndDie(tra('Invalid username or activation code. Maybe this code has already been used.'), \Laminas\Http\Response::STATUS_CODE_400);
+ // Only proceed if password change is allowed
+ if ($can_change_password) {
+ // Validate password change operation
+ $validation_errors = false;
+ if ($_REQUEST["pass"] != $_REQUEST["passAgain"]) {
+ Feedback::error(tra("The passwords do not match"));
+ $validation_errors = true;
}
- }
- // Check that provided user name could log in with old password, otherwise display error and exit
- list($isvalid, $_REQUEST["user"], $error) = $userlib->validate_user($_REQUEST["user"], $_REQUEST["oldpass"]);
- if (! $isvalid) {
- Feedback::errorAndDie(tra("Invalid old password"), \Laminas\Http\Response::STATUS_CODE_400);
- }
- if (isset($_REQUEST['email'])) {
- if (empty($_REQUEST['email']) || ! validate_email($_REQUEST['email'], $prefs['validateEmail'])) {
- Feedback::errorAndDie(tra('Your email could not be validated; make sure your email is correct'), \Laminas\Http\Response::STATUS_CODE_400);
+ // Check password policy
+ $polerr = $userlib->check_password_policy($_REQUEST["pass"]);
+ if (strlen($polerr) > 0) {
+ Feedback::error($polerr);
+ $validation_errors = true;
+ }
+ // Also check if new password matches current password hash
+ $current_hash = $userlib->getOne('select `hash` from `users_users` where binary `login`=?', [$user]);
+ if (! empty($current_hash) && password_verify($_REQUEST["pass"], $current_hash)) {
+ Feedback::error(tra("You can not use the same password again"));
+ $validation_errors = true;
+ }
+ // Validate email if provided
+ if (isset($_REQUEST['email'])) {
+ if (empty($_REQUEST['email']) || ! validate_email($_REQUEST['email'], $prefs['validateEmail'])) {
+ Feedback::error(tra('Your email could not be validated; make sure your email is correct'));
+ $validation_errors = true;
+ }
}
- $userlib->change_user_email_only($_REQUEST['user'], $_REQUEST['email']);
- }
- $res = $userlib->change_user_password($_REQUEST["user"], $_REQUEST["pass"]);
- //If the password is successfully changed
- if ($res && $prefs['pass_history_management'] === 'y') {
- // Add new password to history
- $userlib->addPasswordHistory($_REQUEST["user"], $_REQUEST["pass"]);
- }
+ // Only proceed with password change if validation passed
+ if (! $validation_errors) {
+ // Perform password change operation
+ if (isset($_REQUEST['email']) && ! empty($_REQUEST['email'])) {
+ $userlib->change_user_email_only($user, $_REQUEST['email']);
+ }
+ $res = $userlib->change_user_password($user, $_REQUEST["pass"]);
+ if ($res && $prefs['pass_history_management'] === 'y') {
+ $userlib->addPasswordHistory($user, $_REQUEST["pass"]);
+ }
- // Login the user and display Home page
- $_SESSION["$user_cookie_site"] = $_REQUEST["user"];
- $user = $_REQUEST["user"];
- $logslib->add_log('login', 'logged from change_password', $_REQUEST['user'], '', '', $tikilib->now);
+ // Mark reset token as used only after successful password change
+ if (! empty($secure_token) && ! $is_new_user_validation && ! $must_change_password) {
+ $passwordResetLib = new \Tiki\Lib\Auth\PasswordResetLib();
+ $passwordResetLib->markPasswordResetTokenUsed($user, $secure_token);
+ }
- if ($prefs['feature_user_encryption'] === 'y') {
- // Notify CryptLib about the password change
- $cryptlib = TikiLib::lib('crypt');
- $cryptlib->onChangeUserPassword($_REQUEST["oldpass"], $_REQUEST["pass"]);
- }
+ // Handle encryption if enabled
+ if ($prefs['feature_user_encryption'] === 'y' && ! empty($authenticated_oldpass)) {
+ $cryptlib = TikiLib::lib('crypt');
+ $cryptlib->onChangeUserPassword($authenticated_oldpass, $_REQUEST["pass"]);
+ }
- // re-evaluate homepage since we just login the user but not if it's the first time after a clean install
- if ($jitRequest->oldpass->text() !== 'admin') {
- include TIKI_PATH . '/lib/setup/default_homepage.php';
- }
- $homePageUrl = $prefs['tikiIndex']; // set up in lib/setup/default_homepage.php
-
- // Check if a wizard should be run.
- // If a wizard is run, it will return to the $url location when it has completed. Thus no code after $wizardlib->onLogin will be executed
- $wizardlib = TikiLib::lib('wizard');
- $force = $_REQUEST["user"] == 'admin';
- $wizardlib->onLogin($user, $homePageUrl, $force);
-
- // Go to homepage or url_after_validation
- $accesslib = TikiLib::lib('access');
- if (! empty($prefs['url_after_validation']) && ! empty($_REQUEST['new_user_validation'])) {
- $access->redirect($prefs['url_after_validation']);
- } else {
- $accesslib->redirect($homePageUrl);
+ // Login user as part of the change operation
+ $userlib->update_expired_groups();
+ $loginlib = TikiLib::lib('login');
+ $loginlib->activateSession($user);
+ $logslib->add_log('login', 'logged from change_password', $user, '', '', $tikilib->now);
+ if ($jitRequest->oldpass->text() !== 'admin') {
+ include TIKI_PATH . '/lib/setup/default_homepage.php';
+ }
+ $homePageUrl = $prefs['tikiIndex'];
+ $wizardlib = TikiLib::lib('wizard');
+ $force = $user == 'admin';
+ $wizardlib->onLogin($user, $homePageUrl, $force);
+ $accesslib = TikiLib::lib('access');
+ if (! empty($prefs['url_after_validation']) && ! empty($_REQUEST['new_user_validation'])) {
+ $access->redirect($prefs['url_after_validation']);
+ } else {
+ $accesslib->redirect($homePageUrl);
+ }
+ }
}
+ // If authentication failed or validation failed, fall through to display the form
}
-// Display the template
+// Display password change form
global $prefs;
$prefs['language'] = $tikilib->get_user_preference($_REQUEST['user'], 'language', $prefs['site_language']);
$smarty->assign('email', $userlib->get_user_email($_REQUEST['user']));
-
-// disallow robots to index page:
$smarty->assign('metatag_robots', 'NOINDEX, NOFOLLOW');
$smarty->assign('mid', 'tiki-change_password.tpl');
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/7cc02fcd778b11b5af79f2d399e94a26820c0681
--
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/7cc02fcd778b11b5af79f2d399e94a26820c0681
You're receiving this email because of your account on gitlab.com.
_______________________________________________
TikiWiki-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs