Restricting access to ASP.NET 2 pages - Authentication

This article describes how to set up a website using ASP.NET 2 in such a way that:

  • No one can view the pages on the website unless they login. If they try to view a page and are not logged in, they are taken to a login page instead and are forced to login.
  • Logged in users can see certain pages on the site according to certain parameters set on a user-by-user basis. So, each user has a profile that determines which category of pages they have access to.

This sounds like it may take some work to set up, but actually it is easy because ASP.NET 2 has built-in Membership and Role Management facilities.

Let's define some terms...

Authentication is the term used to describe the login process. ASP.NET calls this the Membership Service, and provides components that let you set up login screens very easily.

Authorization is the way of specifying which authenticated user can see which pages of the website. ASP.NET calls this Role Management.

Personalization is the way that ASP.NET can store special information about users that can be used to customize the way that information is presented to each user.

ASP.NET 2's built-in support for authentication and authorization uses a special SQL Server database that is created for you by a wizard. To enable the authentication system, edit your web.config file and find the <system.web> section. In there you must add a new section to tell ASP.NET to use the "Forms" style of authentication. There are other styles, but this one will get us what we want very easily. Just add this line:

<authentication mode="Forms"/>

Now go to the WebSite Adminitration Tool for your website, which is accessed from Solution Explorer by clicking on the icon of the "hammer and world". Clicking on this for the first time causes a wizard to be run that takes a while to do its tasks. The most noticable result is that a new database called ASPNETDB.MDF appears in your App_Data folder. This is the database where all the usernames and passwords will be stored. The Website Administration Tool will eventually start up, but you don't need it. You just started it to kick-off the wizard. ASPNETDB.MDF is just a stand-alone SQL Server database, that you can open up and look at if you like. It is where all the usernames, passwords and profile details are going to be stored.

Creating users

As it stands, there are no users created for your website, so obviously no one will be able to login. To make the users, add a new file to your project called something such as "create_users.aspx". This is the page that we will use to create new users, and it uses an ASP.NET 2 component that does all the work really easily. Just add a single CreateUserWizard control to it (which you can find in the login section of your component toolbox) and try it out.

Note about passwords: I got stuck for ages at this point because I couldn't add a new user to the system no matter how hard I tried. The reason is that by default the password security level is set to a very high level. You need to include uppercase, lower case, numbers and non-alphanumeric characters in the password (for example "pA55w*rd") or else you get an error. Unfortunately this error message doesn't tell you all restrictions that are actually in force.

Having added a user, take a look in the ASPNETDB.MDF database, and sure enough the new user will have been added to the aspnet_users table in there.

Storing user details in their profile

ASP.NET 2 has a built-in system to enable you to define arbitrary properties for a user and store them in the ASPNETDB.MDF database. This is referred to as the user's profile. To add a new profile property, edit the web.config file and add the new property into the <system.web> section. For example, here I add a property to define what level of membership they have, i.e. gold member, bronze member etc:

<profile>
    <properties>
        <add name="MemberLevel" />
    </properties>
</profile> 

The CreateUserWizard is very powerful, and it allows you to customise it to add extra stages in. I wanted to incorporate a new step into the CreateUserWizard to let the person subscribe when they were being created as a new user. I wanted to add this in before the last step of the Wizard. But when I tried I got an error: "This property cannot be set for anonymous users". The reason for this is that between the first step and the last step of the wizard, the user is not actually logged in; they only get logged in on the very last step. So, as the Profile property that I want to set is not available to anonymous users, I can't set this property until the user has completed the Wizard. To get around this I made a new page called modify_profile.aspx and configured the button on the last page of the CreateUserWizard to take the user to this page:

protected void ContinueButton_Click(object sender, EventArgs e)
{
    Response.Redirect("profile_details.apsx");
}

Then, in this extra page I set the Profile.MemberLevel property for them according to how much they have paid.

LoginStatus and LoginName

Two other useful controls provided by ASP.NET 2 are the LoginStatus and LoginName controls. The first control simply shows a link-text saying either "Login" if you are not logged in, or "Logout" if you are currently logged in. Clicking this link obviously logs you out or logs you in. The second control displays the username of the currently logged in user. I use this to display a simple "Welcome back username" message on the website homepage. This is useful for people to see whether the website has remembered them and logged them in or not.

Problems with the NETWORK SERVICE id

When setting up authentication, it is common to encounter this error message:

Cannot open user default database. Login failed.
Login failed for user 'NT AUTHORITY\NETWORK SERVICE'.

Most typically this happens when you have set up all your authentication on your own PC, and then move the application to the real server. You may find that you can login if you are using that server, but can't login from another PC. The reason for this is that there are two built-in accounts that need permission to write to the ASPNETDB.MDF file in the App_Data folder of your website. These accounts are "ASPNET" and "NETWORK SERVICE". The best thing to do is to use Explorer to navigate to the App_Data folder of the website and set the security options so that ASPNET and NETWORK SERVICE have modify permissions on this folder and all the files in it.