Much Overflow
Much Overflow

Reputation: 3140

Complex password validation using regex

I am trying to create a javascript regular expression for password validation. The rules for a password to get accepted are

I found an example online and modified it like following

(?=.*[0-9]{2,})(?=.*[a-z])(?=.*[A-Z]{2,}).{12,}

However this still misses the special character requirement and only works if the upper case characters and numbers are in subsequent order. These are the results I got with this one

aMMericano11 - true
aMmeRican1o1 - false

I wanted the second one to be accepted too with the addition of special characters of course.

Can anyone help me on this?

Upvotes: 0

Views: 2803

Answers (3)

drf
drf

Reputation: 8699

The problem is in the lookahead:

(?=.*[0-9]{2,})

This pattern requires that the pattern [0-9]{2,} (e.g., a 2-digit number) appear in the text. What you probably intended was:

(?=(.*[0-9]){2,})

This allows the numbers to be separated by other characters, rather than being consecutive.

The same problem applies to the capital letters rule. Piecing this together, the final expression would be:

(?=(.*[0-9]){2,})(?=.*[\*^!])(?=.*[a-z])(?=(.*[A-Z]){2,}).{12,}

The expression will match if and only if the password meets the validity rules. If more granularity is needed (e.g., to detect that a specific rule is violated), you may need to break the expression into smaller expressions.

Upvotes: 5

Harpreet Singh
Harpreet Singh

Reputation: 2671

Agreed with @Niet the Dark Absol

But still if you want to do this with regEx then break it as:

'ab2c3F*ghijKM'.match(/[\w\W]{12,}/) //Should contain 12 characters or more

'ab2c3F*ghijKM'.match(/[*^!]/) //Should contain one of these special characters * ^ !

'ab2c3F*ghijK'.match(/[A-Z]/g).length>=2 //At least two uppercase characters

'ab2c3F*ghijK'.match(/[\d]/g).length>=2 //At least two numbers characters

'23Fa*K'.match(/[a-z]/) //At least one lowercase characters

Then apply && operations on all these expressions

eg:

var pass = 'ab2cFg*hij3KM';
var isValidInput = pass.match(/[\w\W]{12,}/) && pass.match(/[*^!]/) && (pass.match(/[A-Z]/g).length>=2) && (pass.match(/[\d]/g).length>=2) && pass.match(/[a-z]/)
if(isValidInput) {
    console.log('valid')
} else {
    console.log('invalid')
}

Upvotes: 0

Niet the Dark Absol
Niet the Dark Absol

Reputation: 324750

Disregarding my sarcastic comment about the futility of arbitrary password rules, you are trying to do too much at once.

What you're doing is "does it have 12 letters or more and a symbol from *^! and at least two uppercase letters and at least two numbers and at least one lowercase letter"...

What you should do is:

  • Does it have 12 letters or more? If not, fail and ask for a longer password
  • Does it have a symbol? If not, fail and ask for a symbol
  • Does it have at least two uppercase letters? If not, fail and ask for them.
  • Does it have at least two numbers? If not, fail and ask for them.
  • Does it have at least one lowercase letter? If not, fail and ask for it.

Break down big problems into small problems, and you'll end up with better user experience because you can tell your user exactly what you want from them.

Upvotes: 6

Related Questions