Consider more user inputs when calculating zxcvbn score (#11180)
* Consider more user inputs when calculating zxcvbn score * MatrixClientPeg.getHomeserverName may throw
This commit is contained in:
parent
90e65e8490
commit
4044c2aa66
3 changed files with 22 additions and 6 deletions
|
@ -31,6 +31,8 @@ interface IProps extends Omit<IInputProps, "onValidate" | "element"> {
|
||||||
minScore: 0 | 1 | 2 | 3 | 4;
|
minScore: 0 | 1 | 2 | 3 | 4;
|
||||||
value: string;
|
value: string;
|
||||||
fieldRef?: RefCallback<Field> | RefObject<Field>;
|
fieldRef?: RefCallback<Field> | RefObject<Field>;
|
||||||
|
// Additional strings such as a username used to catch bad passwords
|
||||||
|
userInputs?: string[];
|
||||||
|
|
||||||
label: string;
|
label: string;
|
||||||
labelEnterPassword: string;
|
labelEnterPassword: string;
|
||||||
|
@ -57,7 +59,7 @@ class PassphraseField extends PureComponent<IProps> {
|
||||||
deriveData: async ({ value }): Promise<zxcvbn.ZXCVBNResult | null> => {
|
deriveData: async ({ value }): Promise<zxcvbn.ZXCVBNResult | null> => {
|
||||||
if (!value) return null;
|
if (!value) return null;
|
||||||
const { scorePassword } = await import("../../../utils/PasswordScorer");
|
const { scorePassword } = await import("../../../utils/PasswordScorer");
|
||||||
return scorePassword(MatrixClientPeg.get(), value);
|
return scorePassword(MatrixClientPeg.get(), value, this.props.userInputs);
|
||||||
},
|
},
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -473,6 +473,7 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
|
||||||
value={this.state.password}
|
value={this.state.password}
|
||||||
onChange={this.onPasswordChange}
|
onChange={this.onPasswordChange}
|
||||||
onValidate={this.onPasswordValidate}
|
onValidate={this.onPasswordValidate}
|
||||||
|
userInputs={[this.state.username]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import zxcvbn, { ZXCVBNFeedbackWarning } from "zxcvbn";
|
||||||
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import { _t, _td } from "../languageHandler";
|
import { _t, _td } from "../languageHandler";
|
||||||
|
import { MatrixClientPeg } from "../MatrixClientPeg";
|
||||||
|
|
||||||
const ZXCVBN_USER_INPUTS = ["riot", "matrix"];
|
const ZXCVBN_USER_INPUTS = ["riot", "matrix"];
|
||||||
|
|
||||||
|
@ -59,20 +60,32 @@ _td("Short keyboard patterns are easy to guess");
|
||||||
*
|
*
|
||||||
* @param {string} password Password to score
|
* @param {string} password Password to score
|
||||||
* @param matrixClient the client of the logged in user, if any
|
* @param matrixClient the client of the logged in user, if any
|
||||||
|
* @param userInputs additional strings such as the user's name which should be considered a bad password component
|
||||||
* @returns {object} Score result with `score` and `feedback` properties
|
* @returns {object} Score result with `score` and `feedback` properties
|
||||||
*/
|
*/
|
||||||
export function scorePassword(matrixClient: MatrixClient | null, password: string): zxcvbn.ZXCVBNResult | null {
|
export function scorePassword(
|
||||||
|
matrixClient: MatrixClient | null,
|
||||||
|
password: string,
|
||||||
|
userInputs: string[] = [],
|
||||||
|
): zxcvbn.ZXCVBNResult | null {
|
||||||
if (password.length === 0) return null;
|
if (password.length === 0) return null;
|
||||||
|
|
||||||
const userInputs = ZXCVBN_USER_INPUTS.slice();
|
const inputs = [...userInputs, ...ZXCVBN_USER_INPUTS];
|
||||||
if (matrixClient) {
|
if (matrixClient) {
|
||||||
userInputs.push(matrixClient.getUserIdLocalpart()!);
|
inputs.push(matrixClient.getUserIdLocalpart()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
let zxcvbnResult = zxcvbn(password, userInputs);
|
try {
|
||||||
|
const domain = MatrixClientPeg.getHomeserverName();
|
||||||
|
inputs.push(domain);
|
||||||
|
} catch {
|
||||||
|
// This is fine
|
||||||
|
}
|
||||||
|
|
||||||
|
let zxcvbnResult = zxcvbn(password, inputs);
|
||||||
// Work around https://github.com/dropbox/zxcvbn/issues/216
|
// Work around https://github.com/dropbox/zxcvbn/issues/216
|
||||||
if (password.includes(" ")) {
|
if (password.includes(" ")) {
|
||||||
const resultNoSpaces = zxcvbn(password.replace(/ /g, ""), userInputs);
|
const resultNoSpaces = zxcvbn(password.replace(/ /g, ""), inputs);
|
||||||
if (resultNoSpaces.score < zxcvbnResult.score) zxcvbnResult = resultNoSpaces;
|
if (resultNoSpaces.score < zxcvbnResult.score) zxcvbnResult = resultNoSpaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue