From 066f72fcdb74cd5df17af6864c152ac5e8bad09e Mon Sep 17 00:00:00 2001 From: Panagiotis <27917356+panoschal@users.noreply.github.com> Date: Thu, 11 Mar 2021 00:14:55 +0200 Subject: [PATCH 1/2] feat: require strong password in forgot password form --- .../structures/auth/ForgotPassword.js | 22 ++++++++++++++++--- src/i18n/strings/en_EN.json | 1 + 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/components/structures/auth/ForgotPassword.js b/src/components/structures/auth/ForgotPassword.js index 5a39fe9fd9..45270323b0 100644 --- a/src/components/structures/auth/ForgotPassword.js +++ b/src/components/structures/auth/ForgotPassword.js @@ -18,7 +18,7 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import { _t } from '../../../languageHandler'; +import { _t, _td } from '../../../languageHandler'; import * as sdk from '../../../index'; import Modal from "../../../Modal"; import PasswordReset from "../../../PasswordReset"; @@ -27,6 +27,9 @@ import classNames from 'classnames'; import AuthPage from "../../views/auth/AuthPage"; import CountlyAnalytics from "../../../CountlyAnalytics"; import ServerPicker from "../../views/elements/ServerPicker"; +import PassphraseField from '../../views/auth/PassphraseField'; + +const PASSWORD_MIN_SCORE = 3; // safely unguessable: moderate protection from offline slow-hash scenario. // Phases // Show the forgot password inputs @@ -135,10 +138,14 @@ export default class ForgotPassword extends React.Component { // refresh the server errors, just in case the server came back online await this._checkServerLiveliness(this.props.serverConfig); + await this['password_field'].validate({ allowEmpty: false }); + if (!this.state.email) { this.showErrorDialog(_t('The email address linked to your account must be entered.')); } else if (!this.state.password || !this.state.password2) { this.showErrorDialog(_t('A new password must be entered.')); + } else if (!this.state.passwordFieldValid) { + this.showErrorDialog(_t('Please choose a strong password')); } else if (this.state.password !== this.state.password2) { this.showErrorDialog(_t('New passwords must match each other.')); } else { @@ -184,6 +191,12 @@ export default class ForgotPassword extends React.Component { }); } + onPasswordValidate(result) { + this.setState({ + passwordFieldValid: result.valid, + }); + } + renderForgot() { const Field = sdk.getComponent('elements.Field'); @@ -228,12 +241,15 @@ export default class ForgotPassword extends React.Component { />
- this['password_field'] = field} + onValidate={(result) => this.onPasswordValidate(result)} onFocus={() => CountlyAnalytics.instance.track("onboarding_forgot_password_newPassword_focus")} onBlur={() => CountlyAnalytics.instance.track("onboarding_forgot_password_newPassword_blur")} autoComplete="new-password" diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 833a8c7838..9539b3096e 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2662,6 +2662,7 @@ "Failed to send email": "Failed to send email", "The email address linked to your account must be entered.": "The email address linked to your account must be entered.", "A new password must be entered.": "A new password must be entered.", + "Please choose a strong password": "Please choose a strong password", "New passwords must match each other.": "New passwords must match each other.", "Changing your password will reset any end-to-end encryption keys on all of your sessions, making encrypted chat history unreadable. Set up Key Backup or export your room keys from another session before resetting your password.": "Changing your password will reset any end-to-end encryption keys on all of your sessions, making encrypted chat history unreadable. Set up Key Backup or export your room keys from another session before resetting your password.", "New Password": "New Password", From d2f40a859bed446dd104258c94d74621a47cc2b6 Mon Sep 17 00:00:00 2001 From: Panagiotis <27917356+panoschal@users.noreply.github.com> Date: Thu, 1 Apr 2021 12:30:49 +0300 Subject: [PATCH 2/2] define PASSWORD_MIN_SCORE in one place and import from there --- src/components/structures/auth/ForgotPassword.js | 3 +-- src/components/views/auth/RegistrationForm.tsx | 2 +- src/components/views/settings/ChangePassword.js | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/components/structures/auth/ForgotPassword.js b/src/components/structures/auth/ForgotPassword.js index dfbb802d22..6188fdb5e4 100644 --- a/src/components/structures/auth/ForgotPassword.js +++ b/src/components/structures/auth/ForgotPassword.js @@ -29,8 +29,7 @@ import CountlyAnalytics from "../../../CountlyAnalytics"; import ServerPicker from "../../views/elements/ServerPicker"; import PassphraseField from '../../views/auth/PassphraseField'; import {replaceableComponent} from "../../../utils/replaceableComponent"; - -const PASSWORD_MIN_SCORE = 3; // safely unguessable: moderate protection from offline slow-hash scenario. +import { PASSWORD_MIN_SCORE } from '../../views/auth/RegistrationForm'; // Phases // Show the forgot password inputs diff --git a/src/components/views/auth/RegistrationForm.tsx b/src/components/views/auth/RegistrationForm.tsx index 85e0933be9..8f0a293a3c 100644 --- a/src/components/views/auth/RegistrationForm.tsx +++ b/src/components/views/auth/RegistrationForm.tsx @@ -40,7 +40,7 @@ enum RegistrationField { PasswordConfirm = "field_password_confirm", } -const PASSWORD_MIN_SCORE = 3; // safely unguessable: moderate protection from offline slow-hash scenario. +export const PASSWORD_MIN_SCORE = 3; // safely unguessable: moderate protection from offline slow-hash scenario. interface IProps { // Values pre-filled in the input boxes when the component loads diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js index aa635ef974..3a7fb2e2b3 100644 --- a/src/components/views/settings/ChangePassword.js +++ b/src/components/views/settings/ChangePassword.js @@ -28,13 +28,12 @@ import Modal from "../../../Modal"; import PassphraseField from "../auth/PassphraseField"; import CountlyAnalytics from "../../../CountlyAnalytics"; import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { PASSWORD_MIN_SCORE } from '../auth/RegistrationForm'; const FIELD_OLD_PASSWORD = 'field_old_password'; const FIELD_NEW_PASSWORD = 'field_new_password'; const FIELD_NEW_PASSWORD_CONFIRM = 'field_new_password_confirm'; -const PASSWORD_MIN_SCORE = 3; // safely unguessable: moderate protection from offline slow-hash scenario. - @replaceableComponent("views.settings.ChangePassword") export default class ChangePassword extends React.Component { static propTypes = {