Gayan
Gayan

Reputation: 2935

JavaScript RegExp password validation not working

I tried to validate my password using RegExp. I wrote following code,

    var pass = jQuery('#new_password').val(); 
    // Minimum six characters, at least one uppercase letter, one lowercase letter and one number
    var reg = new RegExp("^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{6,}$");
    if (reg.test(pass)) {
        alert(1);
    } else {
        alert(2);
    }

However, even If I entered complex password according to my requirement (Minimum six characters, at least one uppercase letter, one lowercase letter and one number), Condition's true part (if condition) does not execute.

Could someone please help me to solve this? thank you.

Upvotes: 1

Views: 1096

Answers (5)

Zeeshan Siddique
Zeeshan Siddique

Reputation: 77

Try this!

   export function validatePassword(password) {
      // password testing
      const hasUpperCase = /[A-Z]/.test(password)
      const hasLowerCase = /[a-z]/.test(password)
      const hasNumbers = /\d/.test(password)
      const hasSpecial = /\W/.test(password)
      let errors = []
    
      if (password.length < 6) {
        errors.push('Password must be at least 6 characters long.')
      }
      if (!hasUpperCase) {
        errors.push('Password must contain at least one uppercase letter.')
      }
      if (!hasLowerCase) {
        errors.push('Password must have at least one lowercase letter.')
      }
      if (!hasNumbers) {
        errors.push('Password must have at least one number.')
      }
      if (!hasSpecial) {
        errors.push('Password must have at least one special character.')
      }
    
      return errors
    }
    
    export default validatePassword;

Upvotes: 0

Robo Mop
Robo Mop

Reputation: 3553

You can try this out:

^(?=.*?[a-z])(?=.*?[A-Z])(?=.*?\d)[A-Za-z\d@$!%*#?&]{6,}$

As shown here: https://regex101.com/r/GAkedL/1

Explanation -

Here, we match each condition separately, because in your code the first lookahead implies "followed by either a lowercase or uppercase letter".

(?=.*?[a-z]) tells the regex that the password should have 0 or more characters followed by a lowercase letter
(?=.*?[A-Z]) tells the regex that the password should have 0 or more characters followed by an uppercase letter
(?=.*?\d) tells the regex that the password should have 0 or more characters followed by a digit

Note the addition of ? after .* in each lookahead. This implies that the regex should match as few characters as possible before finding the letter or digit required, which is more efficient.

Upvotes: 1

JoshG
JoshG

Reputation: 6735

You need to make some modifications to your regular expression.

To match a minimum of 6 characters with at least 1 letter and 1 number, you could use the following expression:

"^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$"

But to ensure that at least 1 of the letters is also uppercase, you'll need to add an additional condition. The below expression should match for a minimum of 6 characters, with at least 1 uppercase letter, 1 lowercase letter, and 1 number:

"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$"

Upvotes: 0

rimraf
rimraf

Reputation: 4126

Try something like this instead? Separate each test out so it's a bit more manageable. IMO.

export function validatePassword(password, repeatPassword) {
  // password tests
  const hasUpperCase = /[A-Z]/.test(password)
  const hasLowerCase = /[a-z]/.test(password)
  const hasNumbers = /\d/.test(password)
  const hasSpecial = /\W/.test(password)
  let errors = []

  if (password !== repeatPassword) {
    errors.push('Passwords do not match.')
  }
  if (password.length < 6) {
    errors.push('Password must be at least 6 characters long.')
  }
  if (!hasUpperCase) {
    errors.push('Password must contain at least one uppercase letter.')
  }
  if (!hasLowerCase) {
    errors.push('Password must have at least one lowercase letter.')
  }
  if (!hasNumbers) {
    errors.push('Password must have at least one number.')
  }
  if (!hasSpecial) {
    errors.push('Password must have at least one special character.')
  }

  return errors
}

export default validatePassword;

I find it easier to separate each test instead of one regex. You can also provide the user with the specific failure.

Upvotes: 1

guijob
guijob

Reputation: 4488

Change your regex to:

^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*#?&]{6,}$

not forgetting a g flag.

  • When using: (?=.*[A-Za-z]) it will pass if user types only uppercase or lowercase letters.

  • When using: (?=.*[@$!%*#?&]) you are requiring user to type some special character.

    var pass = 'TestString123'; 
    // Minimum six characters, at least one uppercase letter, one lowercase letter and one number
    var reg = new RegExp(/^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*#?&]{6,}$/g);
    if (reg.test(pass)) {
        alert(1);
    } else {
        alert(2);
    }

Upvotes: 3

Related Questions