. Guidelines for Secure Password Input
Use the "password" input type
Instead of <input type="text"> you should always use 
<input type="password"> as this lets the browser (and 
the user) know that the contents of that field need to be secured.  Your 
password won't appear on the screen as you type and most browsers also 
won't 'remember' the values entered in 
password fields as they 
do with other form elements.
Confirm password input
Because the 
password input type obscures the text typed, you
should let the user confirm that they haven't made a mistake.  The
simplest way to do this is to have the password entered twice, and then
check that they are identical.
Another method is to display what they've entered as part of a 
'confirmation page'.  The problem here is that you're making the 
password visible in the browser, browser cache, proxy, etc.  For 
security a password should 
never be displayed in HTML or even 
sent by email.
Enforce 'strong' passwords
If you're concerned about security you should have some policy on
what constitutes a valid password.  Some common restrictions are:
- at least n characters
- combination of upper- and lower-case characters
- one or more digits
- not related to other user data (name, address, username, ...)
- not a dictionary word
Leaving the last requirement for now, as it requires a server-side 
script, let's see what's possible using just client-side HTML and 
JavaScript.
Server security
While having a strong password is a good first step, it needs to be 
backed up by additional measures on the server that prevent brute-force 
attacks.  One popular approach is to install Fail2Ban to monitor log 
files and lock out repeat offendors.  Of course that only works if your 
login system reports failed login attempts to a system log file.  
Otherwise your application needs to provide this function.
2. Basic Demonstration
The form below has three input fields: username, pwd1 and pwd2.  
When the form is submitted the 
checkForm script parses the 
input values and returns either 
true or 
false.  If a 
false value is returned then the form submission is cancelled.
This code will work for browsers as far back as Netscape 4 (circa 
1997).
The code behind the form is as follows.  If you're not sure how to 
place this on your page, you might need to read the preceding article on 
Form Validation, or view the HTML 
source of this page.
<script type="text/javascript">
  function checkForm(form)
  {
    if(form.username.value == "") {
      alert("Error: Username cannot be blank!");
      form.username.focus();
      return false;
    }
    re = /^\w+$/;
    if(!re.test(form.username.value)) {
      alert("Error: Username must contain only letters, numbers and underscores!");
      form.username.focus();
      return false;
    }
    if(form.pwd1.value != "" && form.pwd1.value == form.pwd2.value) {
      if(form.pwd1.value.length < 6) {
        alert("Error: Password must contain at least six characters!");
        form.pwd1.focus();
        return false;
      }
      if(form.pwd1.value == form.username.value) {
        alert("Error: Password must be different from Username!");
        form.pwd1.focus();
        return false;
      }
      re = /[0-9]/;
      if(!re.test(form.pwd1.value)) {
        alert("Error: password must contain at least one number (0-9)!");
        form.pwd1.focus();
        return false;
      }
      re = /[a-z]/;
      if(!re.test(form.pwd1.value)) {
        alert("Error: password must contain at least one lowercase letter (a-z)!");
        form.pwd1.focus();
        return false;
      }
      re = /[A-Z]/;
      if(!re.test(form.pwd1.value)) {
        alert("Error: password must contain at least one uppercase letter (A-Z)!");
        form.pwd1.focus();
        return false;
      }
    } else {
      alert("Error: Please check that you've entered and confirmed your password!");
      form.pwd1.focus();
      return false;
    }
    alert("You entered a valid password: " + form.pwd1.value);
    return true;
  }
</script>
expand code box
Remember that, as JavaScript isn't available in all browsers, you 
should user server-side scripting to validate all data before recording 
it in a database or text file.  You might also want to spice up your 
forms using HTML5 Form 
Validation as we've done further down the page.
3. Advanced regular expressions
In the latest browsers - those that support JavaScript 1.5 (Firefox, 
Netscape 6/7, Mozilla, Safari and Opera 7) - you can use more powerful 
regular expressions.  Older browsers 
will not recognise these 
patterns so the following is mostly useful for intranet rather than 
Internet applications.
The code presented above is fine in that it checks everything that we 
wanted to check, but uses a lot of code to test each requirement 
individually and present different error messages.  We're going to show 
you now how to apply the password tests using a single regular 
expression.
Consider the following:
<script type="text/javascript">
  // at least one number, one lowercase and one uppercase letter
  // at least six characters
  var re = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}/;
  var validPassword = re.test(input);
</script>
The type of expression used here is called a 'look-ahead' which tries 
to match the contained regexp against the 'future' part of the 
string.
Translation:
- matches a string of six or more characters;
- that contains at least one digit (\d is shorthand for [0-9]);
- at least one uppercase character; and
- at least one lowercase character:
| input | result of test | reason | 
|---|
| abcABC | false | no numbers | 
| abc123 | false | no uppercase characters | 
| abAB1 | false | too short | 
| abAB12 | true | - | 
| Aa123456 | true | - | 
If you are using a supported browser you can use the form 
below to test the regular expression:
If you want to restrict the password to ONLY letters and numbers (no
spaces or other characters) then only a slight change is required. 
Instead of using 
. (the wildcard) we use 
\w:
<script type="text/javascript">
  // at least one number, one lowercase and one uppercase letter
  // at least six characters that are letters, numbers or the underscore
  var re = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])\w{6,}$/;
  var validPassword = re.test(input);
</script>
The 
\w is shorthand for 'any letter, number or the 
underscore character'.
Again, you can use the form below to test this regular expression:
4. Sample HTML and JavaScript code
You might implement this code on your own website as follows:
<script type="text/javascript">
  function checkPassword(str)
  {
    var re = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])\w{6,}$/;
    return re.test(str);
  }
  function checkForm(form)
  {
    if(form.username.value == "") {
      alert("Error: Username cannot be blank!");
      form.username.focus();
      return false;
    }
    re = /^\w+$/;
    if(!re.test(form.username.value)) {
      alert("Error: Username must contain only letters, numbers and underscores!");
      form.username.focus();
      return false;
    }
    if(form.pwd1.value != "" && form.pwd1.value == form.pwd2.value) {
      if(!checkPassword(form.pwd1.value)) {
        alert("The password you have entered is not valid!");
        form.pwd1.focus();
        return false;
      }
    } else {
      alert("Error: Please check that you've entered and confirmed your password!");
      form.pwd1.focus();
      return false;
    }
    return true;
  }
</script>
<form method="POST" action="form-handler.php" onsubmit="return checkForm(this);">
<p>Username: <input type="text" name="username"></p>
<p>Password: <input type="password" name="pwd1"></p>
<p>Confirm Password: <input type="password" name="pwd2"></p>
<p><input type="submit"></p>
</form>
As you can see, it's well worth learning the intricacies of regular
expressions.  They can be used not just in JavaScript, but also PHP,
Perl, Java and many other languages.  Some text editors (not just vi)
also allow them when searching for or replacing text.
5. HTML5 Form Validation
We earlier mentioned HTML5 form validation.  This is a new technique 
available in modern browsers and definitely the way of the future.  A 
few simple form attributes can have the same effect as reams of 
JavaScript code libraries.
Here we have an enhanced version of the above code where we've added 
HTML5 
required and 
pattern elements to apply regular 
expression tests within the form itself in supporting browsers.  
Helpfully the regular expression syntax is identical with just the 
/^ and 
$/ removed.
We've also added a tricky little 
onchange handler to the 
first password field which updates the pattern required by the second 
password field - in effect forcing them to be identical:
Here you can see a screen shot from Safari of the form being 
completed.  The red/green markers have been implemented using CSS:
In this example it should be clear to the user that the form can only 
be submitted once all three green ticks appear.  In any case browsers 
such as Firefox and Opera will enforce the HTML5 validation rules and 
present messages as shown here:
Presumably the browser messages will change according to the users 
language - something that would never be possible using only 
JavaScript.
All we have changed from the previous example is to add some extra 
attributes to the form input fields.  The rest of the HTML and 
JavaScript remains unaltered:
...
<p>Username: <input type="text" required pattern="\w+" name="username"></p>
<p>Password: <input type="password" required pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z])\w{6,}" name="pwd1" onchange="form.pwd2.pattern = this.value;"></p>
<p>Confirm Password: <input type="password" required pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z])\w{6,}" name="pwd2"></p>
...
The best thing about HTML5 attributes is that they have no effect 
whatsoever on unsupported browsers, so Internet Explorer will act as if 
they are not present and simply run the JavaScript as before.
At this stage both Firefox and Opera enforce HTML5 validation 
attributes in the browser while Safari only lets you use them in 
combination with CSS effects.
6. Customised HTML5 browser alerts
As you can see from the screenshot above the alert message in Firefox 
for when the input doesn't match the 
pattern attribute is 
simply "Please match the requested format.".  Not entirely 
helpful in this case where we have a number of different 
requirements.
Fortunately it is possible to customise this message using just a 
touch of JavaScript.
The only change between this and the previous example is that we've 
modified the 
onchange handler for the Password input and added 
one for Confirm Password:
...
<p>Password: <input type="password" required pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z])\w{6,}" name="pwd1" onchange="
  this.setCustomValidity(this.validity.patternMismatch ? 'Password must contain at least 6 characters, including UPPER/lowercase and numbers' : '');
  if(this.checkValidity()) form.pwd2.pattern = this.value;
"></p>
<p>Confirm Password: <input type="password" required 
pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z])\w{6,}" name="pwd2" onchange="
  this.setCustomValidity(this.validity.patternMismatch ? 'Please enter 
the same Password as above' : '');
"></p>
...
When the Password input is changed we check its 
validity.patternMismatch flag to see whether it matches the 
pattern attribute.  If it doesn't match we set a custom error 
message to appear when the form is submitted.
Whenever 
setCustomValidity() has been used to set a custom 
message the field in question will be regarded as invalid and prevent 
the form from submitting (at least in Firefox and Opera).  To reverse 
this it needs to be set to blank, which we do when the input matches our 
regex rules.
The custom message we have set appears in Firefox as shown here:
You can see from the code that we have applied a similar technique to 
the Confirm Password field so it will now display "Please enter the 
same Password as above" if there is a mismatch between the two 
fields.  Basically what we've achieved here is to replicate our 
JavaScript validation script using HTML5.
Because we are only checking for 
patternMismatch we are not 
affecting the other default validation options - namely the 
required attribute - so submitting the form with blank fields 
will still display the generic "Please fill out this field" 
alert message.  To override those errors you would need to check the 
validity.valueMissing flag.
7. Conclusions
As you can see there's a lot involved in providing a rich user 
experience even for something as simple as changing a password.  To 
summarise what we've covered:
- Always start by emailing new users a random password or unique activation link;
- Use the password input type to prevent passwords appearing on screen;
- Decide what constitutes a 'strong' password for your system and enforce it:
- server-side for spambots and users with JavaScript disabled;
- using JavaScript for browsers that don't support HTML5 validation;
- using HTML5 for a more user-friendly experience;
 
- Use CSS rules to highlight valid/invalid input for browsers that don't have alerts built-in; and
- Customise the HTML5 error messages where appropriate for improved usability;
Most of all don't feel you have to install massive JavaScript or 
jQuery libraries just to validate a form.  By taking advantage of new 
browser standards as show in this article you can save time and 
resources and at the same time provide a better user experience.