Loading Dockerfile +1 −0 Original line number Diff line number Diff line Loading @@ -108,6 +108,7 @@ RUN patch -u ${BASE_DIR}/lib/private/L10N/Factory.php -i ${TMP_PATCH_DIR}/032-se # UserConfigChangedEvent Ref: https://github.com/nextcloud/server/pull/42039 RUN cd ${BASE_DIR} && patch -p1 < ${TMP_PATCH_DIR}/036-user-config-change-event.patch RUN patch -u ${BASE_DIR}/custom_apps/integration_google/lib/Service/GoogleDriveAPIService.php -i ${TMP_PATCH_DIR}/039-fix-slow-google-import-job.patch RUN cd ${BASE_DIR} && patch -p1 < ${TMP_PATCH_DIR}/040-password-length-rules.patch RUN rm -rf ${TMP_PATCH_DIR} Loading patches/040-password-length-rules.patch 0 → 100644 +149 −0 Original line number Diff line number Diff line Subject: [PATCH] New password length rules for change and forgot password Enforce minimum length of 12 and maximum length of 128 for personal password change and lost-password reset flows (frontend and backend). --- ./apps/settings/src/components/PasswordSection.vue +++ ./apps/settings/src/components/PasswordSection.vue-new @@ -16,7 +16,8 @@ <NcPasswordField id="new-pass" :label="t('settings', 'New password')" :value.sync="newPass" - :maxlength="469" + :minlength="12" + :maxlength="128" autocomplete="new-password" autocapitalize="none" spellcheck="false" @@ -24,7 +25,7 @@ <NcButton type="primary" native-type="submit" - :disabled="newPass.length === 0 || oldPass.length === 0"> + :disabled="newPass.length < 12 || newPass.length > 128 || oldPass.length === 0"> {{ t('settings', 'Change password') }} </NcButton> </form> @@ -54,6 +55,14 @@ }, methods: { changePassword() { + if (this.newPass.length < 12) { + showError(t('settings', 'Password must be at least 12 characters long')) + return + } + if (this.newPass.length > 128) { + showError(t('settings', 'Password must not exceed 128 characters')) + return + } axios.post(generateUrl('/settings/personal/changepassword'), { oldpassword: this.oldPass, newpassword: this.newPass, --- ./apps/settings/lib/Controller/ChangePasswordController.php +++ ./apps/settings/lib/Controller/ChangePasswordController.php-new @@ -65,8 +65,27 @@ return $response; } + if ($newpassword === null) { + return new JSONResponse([ + 'status' => 'error', + 'data' => [ + 'message' => $this->l->t('Unable to change personal password'), + ], + ]); + } + + $newPasswordLength = strlen($newpassword); + if ($newPasswordLength < 12) { + return new JSONResponse([ + 'status' => 'error', + 'data' => [ + 'message' => $this->l->t('Password must be at least 12 characters long'), + ], + ]); + } + try { - if ($newpassword === null || strlen($newpassword) > IUserManager::MAX_PASSWORD_LENGTH || $user->setPassword($newpassword) === false) { + if ($newPasswordLength > 128 || $user->setPassword($newpassword) === false) { return new JSONResponse([ 'status' => 'error', 'data' => [ @@ -115,15 +134,25 @@ ]); } - if (strlen($password) > IUserManager::MAX_PASSWORD_LENGTH) { + $passwordLength = strlen($password); + if ($passwordLength < 12) { return new JSONResponse([ 'status' => 'error', 'data' => [ - 'message' => $this->l->t('Unable to change password. Password too long.'), + 'message' => $this->l->t('Password must be at least 12 characters long'), ], ]); } + if ($passwordLength > 128) { + return new JSONResponse([ + 'status' => 'error', + 'data' => [ + 'message' => $this->l->t('Password must not exceed 128 characters'), + ], + ]); + } + $currentUser = $this->userSession->getUser(); $targetUser = $this->userManager->get($username); if ($currentUser === null || $targetUser === null --- ./core/src/components/login/UpdatePassword.vue +++ ./core/src/components/login/UpdatePassword.vue-new @@ -12,6 +12,8 @@ v-model="password" type="password" name="password" + minlength="12" + maxlength="128" autocomplete="new-password" autocapitalize="none" spellcheck="false" @@ -84,6 +86,19 @@ this.error = false this.message = '' + if (this.password.length < 12) { + this.error = true + this.message = t('core', 'Password must be at least 12 characters long') + this.loading = false + return + } + if (this.password.length > 128) { + this.error = true + this.message = t('core', 'Password must not exceed 128 characters') + this.loading = false + return + } + try { const { data } = await Axios.post(this.resetPasswordTarget, { password: this.password, --- ./core/Controller/LostController.php +++ ./core/Controller/LostController.php-new @@ -204,9 +204,13 @@ $this->eventDispatcher->dispatchTyped(new BeforePasswordResetEvent($user, $password)); \OC_Hook::emit('\OC\Core\LostPassword\Controller\LostController', 'pre_passwordReset', ['uid' => $userId, 'password' => $password]); - if (strlen($password) > IUserManager::MAX_PASSWORD_LENGTH) { - throw new HintException('Password too long', $this->l10n->t('Password is too long. Maximum allowed length is 469 characters.')); + $passwordLength = strlen($password); + if ($passwordLength < 12) { + throw new HintException('Password too short', $this->l10n->t('Password must be at least 12 characters long')); } + if ($passwordLength > 128) { + throw new HintException('Password too long', $this->l10n->t('Password must not exceed 128 characters')); + } if (!$user->setPassword($password)) { throw new Exception(); Loading
Dockerfile +1 −0 Original line number Diff line number Diff line Loading @@ -108,6 +108,7 @@ RUN patch -u ${BASE_DIR}/lib/private/L10N/Factory.php -i ${TMP_PATCH_DIR}/032-se # UserConfigChangedEvent Ref: https://github.com/nextcloud/server/pull/42039 RUN cd ${BASE_DIR} && patch -p1 < ${TMP_PATCH_DIR}/036-user-config-change-event.patch RUN patch -u ${BASE_DIR}/custom_apps/integration_google/lib/Service/GoogleDriveAPIService.php -i ${TMP_PATCH_DIR}/039-fix-slow-google-import-job.patch RUN cd ${BASE_DIR} && patch -p1 < ${TMP_PATCH_DIR}/040-password-length-rules.patch RUN rm -rf ${TMP_PATCH_DIR} Loading
patches/040-password-length-rules.patch 0 → 100644 +149 −0 Original line number Diff line number Diff line Subject: [PATCH] New password length rules for change and forgot password Enforce minimum length of 12 and maximum length of 128 for personal password change and lost-password reset flows (frontend and backend). --- ./apps/settings/src/components/PasswordSection.vue +++ ./apps/settings/src/components/PasswordSection.vue-new @@ -16,7 +16,8 @@ <NcPasswordField id="new-pass" :label="t('settings', 'New password')" :value.sync="newPass" - :maxlength="469" + :minlength="12" + :maxlength="128" autocomplete="new-password" autocapitalize="none" spellcheck="false" @@ -24,7 +25,7 @@ <NcButton type="primary" native-type="submit" - :disabled="newPass.length === 0 || oldPass.length === 0"> + :disabled="newPass.length < 12 || newPass.length > 128 || oldPass.length === 0"> {{ t('settings', 'Change password') }} </NcButton> </form> @@ -54,6 +55,14 @@ }, methods: { changePassword() { + if (this.newPass.length < 12) { + showError(t('settings', 'Password must be at least 12 characters long')) + return + } + if (this.newPass.length > 128) { + showError(t('settings', 'Password must not exceed 128 characters')) + return + } axios.post(generateUrl('/settings/personal/changepassword'), { oldpassword: this.oldPass, newpassword: this.newPass, --- ./apps/settings/lib/Controller/ChangePasswordController.php +++ ./apps/settings/lib/Controller/ChangePasswordController.php-new @@ -65,8 +65,27 @@ return $response; } + if ($newpassword === null) { + return new JSONResponse([ + 'status' => 'error', + 'data' => [ + 'message' => $this->l->t('Unable to change personal password'), + ], + ]); + } + + $newPasswordLength = strlen($newpassword); + if ($newPasswordLength < 12) { + return new JSONResponse([ + 'status' => 'error', + 'data' => [ + 'message' => $this->l->t('Password must be at least 12 characters long'), + ], + ]); + } + try { - if ($newpassword === null || strlen($newpassword) > IUserManager::MAX_PASSWORD_LENGTH || $user->setPassword($newpassword) === false) { + if ($newPasswordLength > 128 || $user->setPassword($newpassword) === false) { return new JSONResponse([ 'status' => 'error', 'data' => [ @@ -115,15 +134,25 @@ ]); } - if (strlen($password) > IUserManager::MAX_PASSWORD_LENGTH) { + $passwordLength = strlen($password); + if ($passwordLength < 12) { return new JSONResponse([ 'status' => 'error', 'data' => [ - 'message' => $this->l->t('Unable to change password. Password too long.'), + 'message' => $this->l->t('Password must be at least 12 characters long'), ], ]); } + if ($passwordLength > 128) { + return new JSONResponse([ + 'status' => 'error', + 'data' => [ + 'message' => $this->l->t('Password must not exceed 128 characters'), + ], + ]); + } + $currentUser = $this->userSession->getUser(); $targetUser = $this->userManager->get($username); if ($currentUser === null || $targetUser === null --- ./core/src/components/login/UpdatePassword.vue +++ ./core/src/components/login/UpdatePassword.vue-new @@ -12,6 +12,8 @@ v-model="password" type="password" name="password" + minlength="12" + maxlength="128" autocomplete="new-password" autocapitalize="none" spellcheck="false" @@ -84,6 +86,19 @@ this.error = false this.message = '' + if (this.password.length < 12) { + this.error = true + this.message = t('core', 'Password must be at least 12 characters long') + this.loading = false + return + } + if (this.password.length > 128) { + this.error = true + this.message = t('core', 'Password must not exceed 128 characters') + this.loading = false + return + } + try { const { data } = await Axios.post(this.resetPasswordTarget, { password: this.password, --- ./core/Controller/LostController.php +++ ./core/Controller/LostController.php-new @@ -204,9 +204,13 @@ $this->eventDispatcher->dispatchTyped(new BeforePasswordResetEvent($user, $password)); \OC_Hook::emit('\OC\Core\LostPassword\Controller\LostController', 'pre_passwordReset', ['uid' => $userId, 'password' => $password]); - if (strlen($password) > IUserManager::MAX_PASSWORD_LENGTH) { - throw new HintException('Password too long', $this->l10n->t('Password is too long. Maximum allowed length is 469 characters.')); + $passwordLength = strlen($password); + if ($passwordLength < 12) { + throw new HintException('Password too short', $this->l10n->t('Password must be at least 12 characters long')); } + if ($passwordLength > 128) { + throw new HintException('Password too long', $this->l10n->t('Password must not exceed 128 characters')); + } if (!$user->setPassword($password)) { throw new Exception();