diff --git a/application/admin-client/cypress/e2e/passwordReset.cy.js b/application/admin-client/cypress/e2e/passwordReset.cy.js index d5568b98..fdfd7c6a 100644 --- a/application/admin-client/cypress/e2e/passwordReset.cy.js +++ b/application/admin-client/cypress/e2e/passwordReset.cy.js @@ -38,7 +38,7 @@ describe('Password Reset', () => { cy.get('input[id="password"]').type('Testpassword1') cy.get('input[id="confirmPassword"]').type('Testpassword1{enter}') cy.contains('Invalid password').should('exist') - cy.contains('must not contain easily guessable').should('exist') + cy.contains('commonly used weak pattern').should('exist') }) it('opens password reset page and enters non-matching passwords', () => { diff --git a/application/common/src/PasswordStrength.ts b/application/common/src/PasswordStrength.ts index a105e29d..a0ccb937 100644 --- a/application/common/src/PasswordStrength.ts +++ b/application/common/src/PasswordStrength.ts @@ -20,9 +20,10 @@ export function checkPasswordStrength(password: string): PasswordStrengthResult if (password.length < 14) { fields.Length = { message: 'Password must be at least 14 characters' } } - if (baseWordRegex.test(password)) { + const commonMatch = password.match(baseWordRegex) + if (commonMatch) { fields.CommonBase = { - message: `Password must not contain easily guessable words (i.e. ${commonPasswordBaseWords.join(', ')})`, + message: `Password contains a commonly used weak pattern: "${commonMatch[0]}". Please choose something less predictable.`, } } if (!/[A-Z]/.test(password)) { diff --git a/application/common/testing/constants.ts b/application/common/testing/constants.ts index 738607da..f444ccaa 100644 --- a/application/common/testing/constants.ts +++ b/application/common/testing/constants.ts @@ -4,17 +4,17 @@ export const TestUsers = { OPERATOR_ADMIN: { email: 'operatoradmin@example.com', - password: 'Loginforadmin1', + password: 'Loginfortests123', id: 96, }, ORG_ADMIN: { email: 'admin@example.com', - password: 'Loginforadmin1', + password: 'Loginfortests123', id: 97, }, ORG_ADMIN_2: { email: 'admin2@example.com', - password: 'Loginforadmin1', + password: 'Loginfortests123', id: 101, }, PARTICIPANT_UNANSWERED: { @@ -37,7 +37,7 @@ export const TestUsers = { }, STUDY_ADMIN: { email: 'studyadmin@example.com', - password: 'Loginforadmin1', + password: 'Loginfortests123', id: 106, }, PASSWORD_RESET_USER: { @@ -102,4 +102,77 @@ export const MIME_TYPES: Record = { // csv: 'text/csv' } -export const commonPasswordBaseWords = ['Password', 'Changeme', 'Welcome'] +export const commonPasswordBaseWords = [ + // Numeric sequences + '000000', + '111111', + '1111111', + '11111111', + '112233', + '123123', + '123321', + '12345', + '123456', + '1234567', + '12345678', + '123456789', + '1234567890', + '12345678910', + '555555', + '654321', + '666666', + '7777777', + '987654321', + + // Common words used as passwords + 'Abc123', + 'Admin', + 'Ashley', + 'Bailey', + 'Baseball', + 'Changeme', + 'Dragon', + 'Football', + 'Google', + 'Iloveyou', + 'Jesus', + 'Letmein', + 'Master', + 'Michael', + 'Monkey', + 'Mustang', + 'Mynoob', + 'Ninja', + 'Password', + 'Qwerty', + 'Secret', + 'Shadow', + 'Sunshine', + 'Superman', + 'Trustno1', + 'Welcome', + + // Compound and modified patterns + 'Aa123456', + 'Aa@123456', + 'Admin123', + 'Admin@123', + 'Admintelecom', + 'P@ssw0rd', + 'Pass@123', + 'Passw0rd', + 'Password1', + + // Keyboard walks and bot-observed patterns + '123qwe', + '18atcskd2w', + '1q2w3e', + '1q2w3e4r', + '1q2w3e4r5t', + '3rjs1la7qe', + 'Qazwsx', + 'Qwerty1', + 'Qwerty123', + 'Qwertyuiop', + 'Zxcvbnm', +] diff --git a/application/user-client/cypress/e2e/registration.cy.js b/application/user-client/cypress/e2e/registration.cy.js index 579d03a0..ecc8e023 100644 --- a/application/user-client/cypress/e2e/registration.cy.js +++ b/application/user-client/cypress/e2e/registration.cy.js @@ -90,7 +90,7 @@ describe('registration', () => { cy.get('[data-cy="reg-confirm-password"]').type('Testpassword1') cy.get('[data-cy="reg-button"]').click() cy.contains('Invalid password').should('exist') - cy.contains('must not contain easily guessable words').should('exist') + cy.contains('commonly used weak pattern').should('exist') }) it('Attempt to register existing email (i.e. no invite) and get correct error message', () => {