Click here to Skip to main content
Click here to Skip to main content

From Custom Authentication to ASP.NET Forms Authentication

By , 5 Nov 2002
 

Introduction

One of the first projects I tackled with .NET, after doing the customary "Hello World" example, was converting a commercial ASP application into ASP.NET. 

The application tasks were to process, store and acknowledge (via email) customers' answers to a competition question and to provide a secure area for company officials to view customer entries and send out bulk mail.

Apart from learning how to implement each step in ASP.NET, I also restructured the application to make it more object-oriented. For the secure area of the site I initially more-or-less faithfully reproduced the original functionality. Then I discovered and investigated ASP.NET's built-in Forms Authentication.

What is authentication?

Authentication is the process of obtaining identification credentials, such as name and password, from a user and validating those credentials against some authority. If the credentials are valid, the entity that submitted the credentials is considered an authenticated identity. Once an identity has been authenticated, the authorization process determines whether that identity has access to a given resource. 

ASP.NET provides two other methods of authentication that are platform-specific with respect to the client, whereas Forms Authentication isn't. A couple of other articles on this site provide more in-depth insight into Forms Authentication. Here, I just provide the basics and discuss the issues I needed to address in my authentication process.

The Problem

A company official (also referred to as an administrator) wants to view the list of names and email addresses of the people who have entered the competition and the answers they've provided. The official may then perform other tasks, such as running queries or sending bulk mail.

The security requirements are:

  1. Access to the pages in the secure area requires the official to log in with a valid user name and password.
  2. Any attempt to navigate to a page in the secure area should redirect a user to the Login page.
  3. It should not be possible to  view any page when the browser is in offline mode, thereby bypassing security.
  4. There should be a limit on the number of login attempts within any browser session. 

Now, this isn't an e-commerce application. No credit card details are being processed. It's not necessary to have rock-solid security. Nevertheless it's worth exploring how security can be breached. 

There is no direct navigation from the customer pages to the secure area but suppose somehow a customer or other user discovers the URL to one of the pages in the secure area. Then our security mechanism will force them to login. It will throw them out after a specified number of invalid attempts (say 3). Though they can shut down the browser and try again, but they don't know that. Hopefully they'll be discouraged. But if not, they'll still have a hard time discovering the correct user name and password. An administrator will be aware that they can restart the browser though. So if they forget their login details they can try again to their heart's content. 

A more serious breach would be a malicious user's hacking the web site, downloading the database and extracting the login details. For this application we are just using a simple Microsoft Access database. The database is password-protected so it can't be opened in Access. But you can open the database in a text editor and perhaps have a poke around (it's mostly gibberish but it does contain the odd English word fragment). We could encrypt the database but we haven't. 

The last possibility (I think) is a network sniffer's intercepting and extracting the user name and password as they are transported across the network. I have not catered for this. But it can be addressed by using Secure Sockets Layer (SSL) to encrypt the user name and password as they are passed over the network. If there is a security breach then a hacker would have access to the names and email addresses of our customers and could send them junk mail. That's it. In the initial design, at least, company officials cannot directly update the database via the web. All operations are read-only. So these restrictions would apply to a hacker too.

Initial Solution

We roll our own authentication functionality. First, define some Session objects in Global.asax.

protected void Session_Start(Object sender, EventArgs e)
{
  // Administrator will only be allowed a certain number of login attempts
  Session["MaxLoginAttempts"] = 3;
  Session["LoginCount"] = 0;
  
  // Track whether they're logged in or not
  Session["LoggedIn"] = "No";
}

The login code looks like this.

// Note: here we are just faithfully reproducing the original ASP behaviour.
// Otherwise we would use ASP.NET authentication.

// Check number of login attempts not exceeded. If it is redirect to failed 
// login page.
int maxLoginAttempts = (int)Session["MaxLoginAttempts"];

if (Session["LoginCount"].Equals(maxLoginAttempts))
{
  Response.Redirect("LoginFail.aspx?reason=maxloginattempts");
}

// Attempt login
if (Request.Form["txtUserName"].Trim() == AdministratorLogin.UserName &&
  Request.Form["txtPassword"].Trim() == AdministratorLogin.Password)
{
  // Success, so we can access customer details.
  Session["LoggedIn"] = "Yes";
  Response.Redirect("CustomerDetails.aspx");
}
else // Fail to login
{
  // Report failure
  string invalidLogin = "Invalid Login.";
  lblMessage.Text = invalidLogin;
  
  // Track the number of login attempts
  int loginCount = (int)Session["LoginCount"];
  loginCount += 1;
  Session["LoginCount"] = loginCount;
}

When the login page is loaded it first checks to see whether the maximum number of login attempts has been exceeded. If it has the user is redirected to the "failed login" page. 

If the user has not exceeded the maximum number of login attempts the user name and password are validated against those returned by the AdministratorLogin object. Here I have just provided a couple of read-only properties which retrieve the user name and password from a persistent store (in this case, a database). If all is OK the user can access the customer details page. If not, an invalid login message is displayed to the user and they can try again up until the allowable number of attempts. 

Once the allowable number of login attempts has been exceeded the user will be unable to attempt a login again without being redirected to the "failed login" page. 

If the user tries to access any other page in the secure area they are automatically directed to the login page. This is because the Page_Load event of each page calls a custom authentication function that looks like this.

/// <span class="code-SummaryComment"><summary>
</span>
/// Authenticates user for access to administration pages.
/// Ensures that page can't be navigated to
/// without user's being online and logged in.
/// <span class="code-SummaryComment"></summary>
</span>
protected void AuthenticateUser()
{
  // Prevent caching, so can't be viewed offline
  Response.Cache.SetCacheability(HttpCacheability.NoCache);

  // Can't navigate to the page unless already logged in.
  // If not already logged in go to login page.
  if (Session["LoggedIn"].Equals("No"))
  {
    Response.Redirect("Login.aspx");
  }
}

Without the first line users can navigate to a secure page when the browser is offline, if the page is in the history list, which is not what we want!

Forms Authentication Solution

The principal effect of using ASP.NET's Forms Authentication mechanism is that we no longer need to track the login state. The AuthenticateUser function above disappears. Nor do we have to write our own code to retrieve the user name and password from the database. But in order to use the mechanism we must add some sections to the web.config file in the application root directory. In the authentication section we replace the default settings with the following: 

<!--<span class="code-comment"> Can also use encryption for passwords. --></span>
<authentication mode="Forms">
  <forms name="FwLoginCookie" loginUrl="Login.aspx">
    <credentials passwordFormat="Clear">
      <user name="4th Wall" password="abc" />
      <user name="Kevin" password="maestro" />
    </credentials>
  </forms>
</authentication>

<!--<span class="code-comment"> Deny access to anonymous (unauthenticated) users. --></span>
<authorization>
  <deny users="?" />
</authorization>

Then, after the closing system.web tag:

<!--<span class="code-comment"> Allow all users access to LoginFail.aspx page. --></span>
<location path="LoginFail.aspx">
  <system.web>
    <authorization>
      <allow users="*" />
    </authorization>
  </system.web>
</location>

The effect of these settings is that all pages in the directory are protected from access except through the login mechanism. Any files in sub-directories are also protected unless they contain their own web.config files with different settings. 

In the authentication section, "FwLoginCookie" is the name of the cookie created by the authentication mechanism. Sometimes we may not want to use cookies. But for the present purposes these pages are for access only by company officials. They won't mind having cookies from themselves so to speak! 

"Login.aspx" is the page to be redirected to if a user accesses any other page in the directory. The credentials section contains a list of valid user names and passwords in clear format. An alternative is to encrypt them. (There is a framework function that can do this.) Instead of putting the user name and password in the web.config file they could be placed in an external XML Users file (or a database). This is the solution we would go for if we wanted to add new users to the system.

The authorization section's settings deny anonymous (i.e., unauthenticated) users access to our pages. 

The location section allows us to override the authentication and authorization checks for the LoginFail.aspx page. We need to do this so that an unauthenticated user can be redirected here when their login fails (i.e., after exceeding the allowable number of login attempts). An alternative is to put the LoginFail.aspx page in another directory or in a sub-directory with its own web.config file.

The revised code looks like this. The Session["LoggedIn"] object is no longer required:

protected void Session_Start(Object sender, EventArgs e)
{
  // Administrator will only be allowed a certain number of login attempts
  Session["MaxLoginAttempts"] = 3;
  Session["LoginCount"] = 0;
}

The Login code now just uses ASP.NET's Forms Authentication methods instead of the custom user name and password checking functionality implemented in the initial solution:

// Check number of login attempts not exceeded. If it is redirect to 
// failed login page.
int maxLoginAttempts = (int)Session["MaxLoginAttempts"];

if (Session["LoginCount"].Equals(maxLoginAttempts))
{
  Response.Redirect("LoginFail.aspx?reason=maxloginattempts");
}

// Attempt login
if (FormsAuthentication.Authenticate(txtUserName.Text.Trim(), 
                                     txtPassword.Text.Trim()))
{
  // Success, create non-persistent authentication cookie.
  FormsAuthentication.SetAuthCookie(txtUserName.Text, false);
  
  // Navigate to Customer Details
  Response.Redirect("CustomerDetails.aspx");
}
else // Fail to login
{
  // Report failure
  string invalidLogin = "Invalid Login.";
  lblMessage.Text = invalidLogin;
  
  // Track the number of login attempts
  int loginCount = (int)Session["LoginCount"];
  loginCount += 1;
  Session["LoginCount"] = loginCount;
}

In the Page_Load event in each protected page we still need to prevent offline viewing.

// Prevent caching, so can't be viewed offline
Response.Cache.SetCacheability(HttpCacheability.NoCache);

That's it. Again, to make it solid, we should also apply SSL to prevent user name and password interception.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Kevin McFarlane
Web Developer
United Kingdom United Kingdom
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
SuggestionThis can be done using ASP.net Configuration Tool PinmemberProgramminfree9-Aug-12 8:02 
Good post. This can also be done using ASP.NET configuration tool without having to write much configuration code. Check this link, it explains the process with screenshots.
GeneralMy vote of 3 PinmemberFrank Kerrigan27-Apr-11 5:40 
not bad
GeneralMy vote of 5 PinmemberArnab.2-Mar-11 4:15 
Nicely Explained
GeneralMy vote of 5 Pinmemberfiggikim123-Jan-11 12:39 
it just saved my ass! been looking for this for a very long time! thanx!!
GeneralNice Article Pinmemberfcis20083-Mar-10 22:35 
Thumbs Up | :thumbsup:
Hi Sir,
 
Thank You so much for this article. It helped me more and I built authentication for my website using your article.
 
If you have an updated version or something advanced, I will appreciate it.
 
Thanks again Smile | :)
GeneralRe: Nice Article PinmemberKevin McFarlane3-Mar-10 23:07 
GeneralRe: Nice Article Pinmemberfcis20084-Mar-10 0:39 
Generalredirection failed from login page to originally requested page PinmemberPranjaliBhide29-Sep-08 21:22 
I developed a site with a reserved section based on roles, when I try to access that page i got redirected correctly to the loginpage and on the address bar i see
the ReturnUrl containig the address to point to:
 
http://localhost/SiteName/login.aspx?ReturnUrl=%2fSiteName%
2fadministrator%2fdefault.aspx
 
administrator/default.aspx is the page I have to reach
I authenticate succesfully but when the following instruction executes without error:
FormsAuthentication.RedirectFromLoginPage(user, chkRemember.Checked)
i still remain in the same page, only user and pwd disappear
 
the address in the bar is still the same....
 
otherwise if i submit incorrect user o pwd I got an error that indicates the redirect correctly fails:
If AuthenticateUser(userEncoded, pwdEncoded, roles) Then
FormsAuthentication.RedirectFromLoginPage("@" & ruoli, chkRemember.Checked)
 
Else
lblLogin.Text = "Access denied!"
End If
 

Any idea?
 
Thankx.
Questionlogin page problem PinmemberPreeti197922-Sep-08 20:19 
hi every body...i have made a login page .........i want a code in c# to check the username exists or not if it exists then a message should be displayed that user name exists otherwise it should be entered in the database(SQL Server 2000)...can anybody help..........
Generalunablle to use Form Authentication PinmemberNigam SAMir18-May-07 21:28 
Hi!
In my application ,startup page is Base.aspx. Base.aspx contains four tabs & an ifrmae. the source of iFrame changes depending upon which tab is clicked. one of tab when clicked of the Base.aspx, then source of iFrame become login.aspx. when valid user is logins, the redirected to BaseTwo.aspx which also contains tabs & a iFrame & source of this iframe changed depending upon tab clicked on BaseTwo.aspx. i want to apply From Authentication in this application. setting web.config is ....
 

<forms loginUrl="login.aspx" path="/" protection="All"></forms>




 
now when i run application login page is loaded instead of startup page Base.aspx & also images are not loaded & give some javascript error. when i commented the setting above in web.config file, there is no error & images loaded.
 
how i apply Form authentication in my application?
 
Thanks & Regards,
SAMir Nigam,
Software Engineer,
STPL, Lucknow, India.

Questionhow can i make my page logoff when page is closed Pinmemberrama charan20-Feb-07 3:54 
hi..
i am using forms authentication in my web appln using asp.net 1.1.
My application session is not logged off when page is closed .
 
can i know how to make the page log off (means session to timeout )when the page is closed ?
 
i mean that the application must take the user to login page when he opens it again after he once closed the page.
 
or how can i implement the above?
 
any suggestions are welcome
thnks for help in advance.
 

Rama Charan Prasad

QuestionHow we Remove the cookie on logoff? Pinmemberdeeban23-Nov-05 8:21 
can anyone help me to remove the authentication cookie when i press the logoff button in #.
 
thankz.........Cry | :(( .
AnswerRe: How we Remove the cookie on logoff? PinmemberAbhijeet Patel3-Feb-06 16:01 
GeneralRe: How we Remove the cookie on logoff? PinmemberShin-Ra22-Oct-06 7:22 
QuestionAuthentication between IIS servers PinmemberRatazanaMor8-Nov-05 6:58 

Hello,
 
I have multiples web applications running on multiples iis servers and the authentication page is on of this iis servers.
 
I use Forms Authentication, with cookies.
 
Can a foreign application have access to the authentication cookie?
 
Thanks in advance,
Pedro
AnswerRe: Authentication between IIS servers Pinmemberdove3930-Jan-07 11:46 
QuestionNew security requirement Pinmemberlet326-Oct-05 0:29 
Hello Kevin, great article!
 
I have some security questions:
* Can we avoid that user opens more than 1 session at the time? How to set web.config file to do that?
* If user leaves his window opened (in online mode) someone can see his pages by clicking explorer button "back". Can we control it without the annoying message "application is attempting to close your window" on logout? (For example in the Page_Load of each protected page we check if his session is still alive?)
 
thanks a lot.Cool | :cool:
Generalquery abt Authentication......... PinmemberSneha Dehariya25-Aug-05 20:17 
Hello All,
i have used the code given in my application, but i am getting errors while writing "FormsAuthentication" and "XMLAuthentication" lines........
cud u pls tell me whole code for the application and the namespaces that shud be included...
 
thanks n regards,
muskaan.
GeneralRe: query abt Authentication......... PinmemberAbhijeet Patel3-Feb-06 16:03 
GeneralSend Bulk email Pinmembermaulik8122-Jun-05 1:05 
Hi!
I am working on one Portal project where I need to send Bulk Email on every thursday Night to the all subscribers. The Portal have have arround 1,000,000 exciting members and as per members there are so many Subscribers.
 
My Problem is how I Send a bulk email to all the subscribes on every thursday night?
 
can ur code work for me?
 
Regards,
maulik
 
Maulik Pandya
QuestionCan I make authorization valid between sessions but timeout after 8 hours Pinmemberchenkaijiang@yahoo.com2-Jun-05 20:04 
Hi, I need to SetAuthCookie so that within 2 hours, the user doesn't need to type password again when he connects to our website. But after 8 hours, it should be timeout (the user is required to type the password if he connects to our website after 8 hours).
 
I've tried:
FormsAuthentication.SetAuthCookie(userName, true);
FormsAuthentication.GetAuthCookie(userName, true).Expires = someTime;
 
But it doesn't work (the user can still login without passowrd after 8 hours).
 
Could anybody give me some suggestion?
 
Regards,
Kaijiang

AnswerRe: Can I make authorization valid between sessions but timeout after 8 hours PinmemberSneha Dehariya27-Aug-05 1:53 
GeneralRe: Can I make authorization valid between sessions but timeout after 8 hours PinsussAnonymous28-Aug-05 17:32 
GeneralRe: Can I make authorization valid between sessions but timeout after 8 hours Pinmemberarvindj21-Oct-05 9:59 
QuestionCan I make authorization valid between sessions but timeout after 8 hours Pinmemberchenkaijiang@yahoo.com2-Jun-05 20:03 
Hi, I need to SetAuthCookie so that within 8 hours, the user doesn't need to type password again when he connects to our website. But after 8 hours, it should be timeout (the user is required to type the password if he connects to our website after 8 hours).
 
I've tried:
FormsAuthentication.SetAuthCookie(userName, true);
FormsAuthentication.GetAuthCookie(userName, true).Expires = someTime;
 
But it doesn't work (the user can still login without passowrd after 8 hours).
 
Could anybody give me some suggestion?
 
Regards,
Kaijiang

AnswerRe: Can I make authorization valid between sessions but timeout after 8 hours Pinsussarvindj :-)21-Oct-05 9:54 
GeneralWhere's the source! PinmembernoSpam2@pls.com24-Feb-05 6:10 
Nice article but I would like to see the source for you assume we know the context and what namespaces to use, and everything else that is tough for novices...
 
- John
GeneralForm based authentication for a web aplication in subdirectory PinmemberMajid Shahabfar26-Oct-03 23:55 
Hi dear,
I have a main ASP.NET project in my wwwroot directory in web server.
now I want to create second ASP.NET project in a subdirectory for example wwwroot\subdir\
and also I want to add form based authentication to the second project. as you know I must do
appropriate changes in web.config files and place it in wwwroot\subdir\ directory because I don't
want change my main project web.config file. but when I place web.config file with authentication
in wwwroot\subdir\ directory my second web application doesn't work properly.

\wwwroot\
main web application
main web.config file
\wwwroot\subdir\
second web application
second web.config file

 
now how can I do this job that my two web.config files don't have conflict with each other?
Thank you in advance.

GeneralRe: Form based authentication for a web aplication in subdirectory Pinmemberdove3930-Jan-07 11:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130617.1 | Last Updated 6 Nov 2002
Article Copyright 2002 by Kevin McFarlane
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid