0

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

  • Should contain 12 characters or more
  • Should contain one of these special characters * ^ !
  • At least two uppercase characters
  • At least two numbers
  • At least one lowercase characters

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?

Much Overflow
  • 3,022
  • 1
  • 19
  • 39
  • 4
    Okay, I'm going to register... Password, let's see... "password". Okay, too short. "password1234" is long enough. Oh, needs a symbol... "password1234!@#$"... Uppercase? All right... "PASSword1234!@#$". Finally! [one week later] Okay, I'm going to log into this website. ... Crap, what's my password? – Niet the Dark Absol May 26 '14 at 15:52
  • 18
    http://xkcd.com/936/ – guido May 26 '14 at 15:53
  • lol. I do understand. It is one of my course work requirements. They wanted us to learn regex and implement this. – Much Overflow May 26 '14 at 15:58
  • 1
    "Complex password validation using regex" - no, using something else. **Definitely not** with regular expressions. **No.** – The Paramagnetic Croissant May 26 '14 at 16:00
  • 4
    @n00b_c0der Please inform your professor that you only choose to partake in good programming practices and will not lower yourself to this tomfoolery. – David May 26 '14 at 16:01
  • Aside from all this nonsense, you should try this yourself and stop outsourcing it to stackoverflow. You might start [here](http://stackoverflow.com/questions/22937618/reference-what-does-this-regex-mean) and [here](http://stackoverflow.com/questions/3802192/regexp-java-for-password-validation/3802238#3802238). I've had enough of these kind of questions. – HamZa May 26 '14 at 16:09
  • Actually, a properly written regex can do an excellent job with password validation. Note however, that this question gets asked a lot - please do a search next time. e.g. [regex for password](http://stackoverflow.com/a/9611715/433790) – ridgerunner May 26 '14 at 16:48

3 Answers3

6

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.

Niet the Dark Absol
  • 301,028
  • 70
  • 427
  • 540
5

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.

drf
  • 7,961
  • 28
  • 46
0

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')
}
Harpreet Singh
  • 2,545
  • 18
  • 30