Fixing Registration & Login Forms – Passwords

Wednesday, September 09 2009 -

Since pretty much the dawn of the internet, registration forms have required you to enter your password twice, and both times all you get are black circles to verify what you have entered.  Here’s an example from everyone’s favorite ecommerce site:

Amazon Registration Form

For a user, this is not a very friendly experience.  How can I be sure that what I typed is what I intended to type?  Yes, that’s what the confirmation entry is there for, but what happens if I type the same incorrect spelling twice in a row?  I know that this has happened to me on more than one occasion, if I am filling out a form without really thinking, and am just typing quickly to get through it.

In a recent Alertbox article, Jakob Nielsen addresses this by explaining the reasons why he believes that we should stop password masking.  If we don’t mask the password entry, then there is no longer a need for the confirm password text box.  I’ve summarized Mr. Nielsen’s key points on why masking passwords are bad here:

  • Users make more mistakes when they can’t see what they are typing, causing them to feel less confident, which in turn leads to more people giving up on registration.
  • Users don’t want to make mistakes, so they choose simple passwords or copy/paste them from a text file.  These both lead to a true lack of security

The concern voiced by many people is that not masking the passwords leads to a lack of security as well, but I don’t really find that to be true.  What is the reason for masked passwords?  It is to prevent someone from seeing what you are typing.  However, there is nothing preventing someone from watching a user type and getting the password that way.  In addition, how often are you entering your password on a website (or any application, really) where someone is standing there over your shoulder, watching you?  When it does happen, you can just ask them to turn around briefly, or turn on password masking (for applications that support it – see my example below).

I also read recently in the comments on a post about whether or not password confirmation is needed the idea that using a plain HTML text box is not as secure as an HTML password textbox when submitting the form data.  The poster apparently believed that some sort of encoding takes place when you use <input type=”password” /> that doesn’t take place with <input type=”text” />.  I can guarantee that that is not true.  Both just contain a text value.  The only way any encoding takes place is if you use SSL for your page request, which encodes everything, not just password text boxes.  To show that both boxes submit data in the same manner, I have created a sample form with three controls: a text box, a password text box and a submit button.  The form performs a “get” so you can see the resulting data in the querystring of the subsequent request.  When I put in the word “test” into both text boxes:

PasswordBoxTest

And then click the Submit button, this is my resulting querystring:

?text=test&password=test

As you can see, both text boxes submit the exact same information, which means that there is no inherent security benefit to using the masked password form element.

So why is the masked password still used?  Because people believe that it is more secure and perhaps more importantly, because it’s what has always been done.  For the latter, even a stickler for standards like Jakob Nielsen believes that in this case, the legacy design component should be abandoned.  Regarding the users’ beliefs about password boxes, as experts in the realms of software and usability, is our jobs to help change that belief and make them feel better about using a simpler, more efficient system.

A Better Way

So, what’s the right way to have passwords on registration and login forms?  Jakob Nielsen suggests just using a plain text box with an optional checkbox to mask the password being typed.  He even suggests that certain high-risk applications, such as bank websites, could have this checkbox checked by default.  I think he has just about hit the nail on the head here.  However, until the general mindset about passwords has changed to understand this new paradigm, I believe one additional element should be considered: a small link that pops up a brief explanation as to why the password is shown in plain text.  I’m not going to focus on that part of it here, because there are any number of tutorials out there to show how to do inline popups (start with the Coda Popup Bubbles sample if you need something to start with).  To show how the rest of this would work, I have created a sample form with an unmasked password box.  Here is the HTML that the form uses:

	<fieldset>
		<legend>Show/Hide Password</legend>
		<label for="username">Username</label>
		<input type="text" id="username" name="username" />
		<label for="password">Password</label>
		<input type="text" id="password" name="password" />
		<input type="password" id="passwordhidden" name="passwordhidden" style="display: none;" />
		<input type="checkbox" id="showpassword" name="showpassword" />
		<label for="showpassword">Hide my password while I am typing</label>
	</fieldset>

I then have some jQuery that runs to show or hide one of the boxes, and keep the values in sync:

	$(document).ready(function() {
		$("#showpassword").click(function() {
			var password = $("#password");
			var passwordhidden = $("#passwordhidden");
			if ($(this).get(0).checked) {
				password.css("display", "none");
				passwordhidden.css("display", "");
				passwordhidden.get(0).value = password.get(0).value;
			}
			else {
				password.css("display", "");
				passwordhidden.css("display", "none");
			}
		});

		$("#passwordhidden").keyup(function() {
			$("#password").get(0).value = $(this).get(0).value;
		});
	});

The key here is that the text box is used as the primary data entry point.  Because of this, whenever it is hidden and the password box is shown, the value from the text box gets set in the password box.  For the reverse, the keyup event is used on the password box, so the text box will always have the correct value.

Here is what the form looks like when first loaded (and text entered):

Visible Password Form Example

And here is what it looks like when the user checks the checkbox to hide the password:

Visible Password Form Example - Masked

As you can see, the user can easily change between masked and unmasked text, however they would like it to be.

An Asp.Net Solution

Taking this solution one step further, I have created a custom .Net control that does all of this work for you.  You can add it to a page just like a standard Asp.Net TextBox control, and in your codebehind, you can access the value with the Text property as well.  To use the control, you simply need to add the dll reference to your web project and then add the following line to your web.config in the pages\config section:

	<add tagPrefix="nex" namespace="Nexus.Web.UI.WebControls" assembly="Nexus.Web.UI.WebControls"/>

Once you’ve done that, you can add the control to any .aspx page you want like this:

	<form id="form1" runat="server">
		<fieldset>
			<legend>Show/Hide Password</legend>
			<nex:PasswordBox runat="server" ID="txtPass" MaskCharactersText="Hide my Password" Label="Password"
				MaskCharactersChecked="false" TextBoxCssClass="entryBox" />
		</fieldset>
	</form>

There really isn’t too much to the control to go through here; it basically renders the HTML just like above and adds both the jQuery framework and the custom jQuery to the page.  It has XML commenting in the code, so you should get intellisense when you are using it in Visual Studio.  A few important notes:

  • The package also includes my utility dll (Nexus.Utility.dll) because it uses some functions within it.  This dll includes several static functions that can prove useful for reducing duplicated code.
  • When using the PasswordBox control, you either need to include an app setting with a name of JQueryFrameworkLocation and a value of the location of your jQuery framework .js file, or you need to include that path when adding the control to your page, via the JQueryFrameworkUrl property.  If you are going to use the control more than once, it is definitely worth using the app setting.

Control Property Information

  • CheckBoxCss: Sets the CssClass on the internal CheckBox control
  • JQueryFrameworkPath: Location of the jQuery framework .js file to use.  If not set, control attempts to use value set in an app setting named JQueryFrameworkLocation.
  • Label: If you set the Label property on the control, an HTML <label> will be added before the TextBox controls that is associated with whichever text control is active.  This lets the user click on the label to give the focus to the currently visible text box.  If this is not set, no <label> is added to the page.
  • MaskCharactersChecked: Boolean – determine if the checkbox for masked characters is checked by default or not.  Defaults to false.
  • MaskCharactersText: Text to display for the label on the mask characters checkbox.
  • Text: Get or set the value of the text for the control (displayed in both internal TextBox controls
  • TextBoxCss: Sets the CssClass on both internal TextBox controls

To see the control in action, check out my PasswordBox sample page.

Downloads

Similar Posts

blog comments powered by Disqus