Article
Securing Passwords in Your Database
When ASP.NET developers think of Web security and authentication, three options typically come to mind: Windows authentication, forms authentication, and passport authentication.
If you're building an Intranet application within your organization, for instance, you might choose to use Windows authentication. Configuring Windows authentication within IIS is fairly straight forward and involves only two steps.
First, we make sure that Integrated Windows Authentication is checked and Anonymous Access is unchecked for a Web application by following the steps outlined below:
- Right-click on the Web app directory within IIS and select Properties.
- Select the Directory Security tab from the application's Properties dialog.
- Select the Edit… button within the Anonymous Access and Authentication control panel.
- Uncheck Anonymous Access and make sure that Integrated Windows Authentication is checked similar to the figure below.

Second, we need only to modify the mode attribute within the authentication tag in the application's Web.config file so that it's set to Windows (which is set by default) as follows:
<authentication mode="Windows" />
That's all there is to it. Whenever users request a page, they'll be asked to supply their Windows username and password. Once logged in, users can be tracked by accessing the user.identity property for the page.
In many scenarios, however, development is focused around forms authentication. Why? Because you wouldn't want manually to create usernames and passwords for the thousands of potential users that would access your site. Assuming you're building a large-scale forum application that is accessible by many users over the Internet, forms authentication would be your best bet because it allows you to store usernames and password within your data store (usually a database table) of choice, then validate your users based on a Web accessible login page similar to this:

In this scenario, users enter their usernames and passwords and click a Login button. The Login button raises a Click event, some sort of validation method is called, and code is executed to compare the values users entered into the text boxes with values contained in a database. Typically, the database is structured with a Users table containing UserID, Username, and Password fields similar to the design shown here.

Now, I've read dozens of articles and a few dozen chapters in books that discuss working with forms authentication and most seem to structure their database table around the simple design shown above. So you're probably asking yourself, "What's the problem?" Well, password information is stored as clear text, so any developer with access to the database has access to the username and password information for all users that subscribe to the application. While it's not a big deal for forum applications, it becomes an issue when you start dealing with online banking applications or even day-trading applications like E*Trade, TD Waterhouse, etc.
One solution to this problem could see us use simplistic hashing and store our passwords within a message digest.
Message Digest and Simplistic Hashing
A message digest is the representation of text in the form of a single string of digits created using a formula called a one-way hash function. A one-way hash function takes an input string (such as a password) and performs some math on it to produce a string of gobbledygook (a digest string). Let's take the password "zak", for instance. I could "hash" that password and the resulting digest would be: D52987198EA2730FD22A38E7976344D843A7FFA0. Doesn't look at all like "zak", does it?
A good hash function makes it extremely difficult to guess an input string that will produce a given digest string. What if you converted your users' passwords into digest strings, and stored those digest strings in the database instead of the actual passwords? Whenever a user logs in, your authentication script could perform the same one-way hash function on the password he or she enters and compare it with the digest string stored in the database. A match means the user entered the right password, and should be granted access to the site.
The big advantage here is that someone who can read your user database (say, a database administrator), can see only the digest strings—not the original passwords! And, because it's practically impossible to find the password to produce a particular message digest, they can't use that information to gain access to your application!
To really appreciate how hashing works, let's create a simple application that uses forms authentication.
Note that all the code included in this article is contained in this downloadable code archive.
Setting up a site to use forms authentication is just as easy as Windows authentication. First, we need only to modify the mode attribute within the authentication tag in the application's Web.config file so that it's set to Forms as follows:
<authentication mode="Forms" />
Second, we can set the users attribute of the deny tag within the authorization section handler to "?" as follows:
<authorization>
<deny users="?" />
</authorization>
Essentially, we'd be denying all anonymous users. Next, we create a registration page (registration.aspx) complete with three TextBox controls and a Button control to handle the user registration. The code should resemble the following:
<form runat="server">
<strong>User Registration</strong><br /><br />
Username:<br />
<asp:TextBox id="txtUsername" runat="server" /><br />
Password:<br />
<asp:TextBox id="txtPassword" runat="server" TextMode="Password" /><br />
Email:<br />
<asp:TextBox id="txtEmail" runat="server" /><br /><br />
<asp:Button id="btnAddCredentials" runat="server" Text="Add Credentials" />
</form>
When viewed in the browser, your page should resemble the image below.

Now that you've seen the UI output of our markup, let's add the OnClick attribute that will call our AddCredentials_Click() method, which we'll build in a minute:
<asp:Button id="btnAddCredentials" runat="server" Text="Add Credentials" OnClick="AddCredentials_Click" />
Now that we have our user interface ironed out, let's create a new database and database table to store the username, password, and email (in case a user happens to forget the password and must reset it, we can send out the instructions to the user's email). For this example, I create a simple Access database called Customers.mdb with a single table called Users. The design for the Users table is outlined below:

When complete, the Datasheet will resemble that shown below.

We can now write the code to store our user's username, hashed password, and email within our database. We start by adding the necessary directives to the top of the page as follows:
<%@ Import Namespace="System.Data.OleDb" %>
<%@ Import Namespace="System.Web.Security" %>
Because we'll be interacting with an Access database, we import the System.Data.OleDb namespace. Similarly, because we'll need to work with the FormsAuthentication classes, we import the System.Web.Security namespace. Next, we can add a code declaration block within the <head> tag of our document, complete with variable declarations and our AddCredentials_Click() method, as follows:
<script runat="server">
Dim objConn As New OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0;Data
Source=C:\Inetpub\wwwroot\PasswordHashing\Database\Customers.mdb")
Dim objCmd As OleDbCommand
Dim sqlCmd As String
Sub AddCredentials_Click(s As Object, e As EventArgs)
sqlCmd = "INSERT INTO Users (Username, Pass, Email)
VALUES (@Username, @Pass, @Email)"
objCmd = New OleDbCommand(sqlCmd, objConn)
objCmd.Parameters.Add("@Username", txtUsername.Text)
objCmd.Parameters.Add("@Pass",
FormsAuthentication.HashPasswordForStoringInConfigFile(txtPassword.Text,
"SHA1"))
objCmd.Parameters.Add("@Email", txtEmail.Text)
objConn.Open()
objCmd.ExecuteNonQuery()
objConn.Close()
End Sub
</script>
For the sake of brevity, I'll assume that you have experience interacting with databases using ASP.NET. At first glance, everything seems fairly straight forward in the code above, except for the use of the HashPasswordForStoringInConfigFile() method of the FormsAuthentication class. This method exists as a way to hash and store a password within the Web.config file. We can use this method for our own purposes, that is, to store hashed passwords into a database.
As you can see, the method accepts two parameters. The first is obviously the text value to use. Since we're retrieving this value from the password text box, we use txtPassword.Text. The second is the digest algorithm to use. In this example, I've use SHA1, which produces a 160 bit digest. You could also use MD5, in which case the result would be a 128 bit digest. Generally speaking, the more bits in a digest string, the harder it is to guess an input string that will produce it.
Involved in the Web since 1995, Zak is founder of and advisor to