Click here to Skip to main content
13,045,984 members (46,235 online)
Click here to Skip to main content
Add your own
alternative version


109 bookmarked
Posted 21 Jun 2012

Understanding and Implementing ASP.NET Custom Forms Authentication

, 21 Jun 2012
Rate this:
Please Sign up or sign in to vote.
Understanding and implementing ASP.NET custom Forms Authentication.


This article talks about ASP.NET the custom Forms Authentication mechanism. We will see how we can use a custom database in unison with the ASP.NET Forms Authentication mechanism to provide the desired level of security to our applications.


We have already seen how we can use ASP.NET Roles and Membership classes to provide authentication and authorization in our applications (refer this). Also, we know about the server controls provided by ASP.NET to facilitate easy implementation of Roles and Membership functionalities in our application.

These Roles and Membership classes come in very handy when we want to provide authentication and authorization in our applications. ASP.NET also provides a way to implement custom Roles and Membership to take more granular control over things.

We might still find ourselves in situations where we need to have our own database for tracking users and their roles. The reasons could be:

  • We have an existing database and we are trying to implement an application using that.
  • The Roles and Membership functionality is overkill for our application.
  • The Roles and Membership functionality is not sufficient for our applications and we need custom data.

In all the above scenarios, we find the need to use ASP.NET Forms Authentication but according to our database schema and our custom written code to handle user management. This is where the beauty of ASP.NET is shown. ASP.NET provides us fully functional and robust functionality for authentication and authorization and yet it gives us the possibility of taking full control and having full customization of the functionalities (which is actually not limited to Authentication related stuff, pretty much all areas of ASP.NET does that).

So what we are trying to do can easily be achieved by having a custom Forms Authentication mechanism. Using a custom Forms Authentication mechanism we can have our own tables to manage users and yet use the existing form authentication mechanism using GenericPrincipal. Let us try to work out an example and see how this can be done.

Using the code

Let us start by getting our requirements clear. We will be implementing a website that has the following structure:

Custom forms authentication article

The top level default page and the login page can be accessed by anyone. The pages in other folders can only be accessed by users in respective roles. Just to understand it in a clear way, let us look at the web.config of the PlatinumUser folder.

			<allow roles="platinum" />
			<deny users="*" />

And the database that we have for user management looks like this.

Custom forms authentication article

We have a user table and every user can have multiple Roles. We will be using this table to authenticate the users.

Note: The database is neither optimized nor normalized as that was not the main intent of this article. A real world example of database will be more optimized and perhaps more complex. The passwords will not be in clear text for sure too.

Now before going ahead, let us look at the little algorithm that we will be following to implement custom forms authentication and achieve the desired functionality.

  1. Configure the application to use Forms Authentication.
  2. Create a login page.
  3. Whenever a user tries to access the restricted area, push him to the Login page.
  4. When the user tries to login, verify his credentials using the database.
  5. If the login is successful, keep the username and his Roles in a Session variable to use it further.
  6. Create an authentication ticket for the user (an encrypted cookie). We can have this persistent or non persistent.
  7. Facilitate the User/Roles extraction using the authentication ticket.
  8. Use the user/Roles found in the last step and create a Principal using that so that the ASP.NET Forms Authentication mechanism can use this data.

Note: Each point in this algorithm can be found emphasized in the explanation below.

We have the algorithm worked out. We will now look at how each step is done. Let us start with Configure the application to use Forms authentication. To do this we need to set the authentication mode in the web.config file.

<authentication mode="Forms">
	<forms loginUrl="Login.aspx" name="MyCustomAuthentication" timeout="30"/>			

This web.config indicates that Forms Authentication will be used in this application. The default loginUrl is Login.aspx. The name of the authentication ticket cookie will be MyCustomAuthentication and if this cookie is created in non persistent mode, then the timeout period for that is 30 minutes.

Now we have our website set to use Forms authentication and we have also specified the default login page so we also took care of #3 of our algorithm, i.e., Whenever user tries to access the restricted area, push him to the Login page. The next thing is to Create a login page.

Custom forms authentication article

Once this login page is done, we need to have some mechanism so that When the user tries to login, verify his credentials using the database. To do this, I have created a small helper class. Ideally this logic will be placed in a Data Access layer or might be present in ORMs. But for the sake of simplicity I have created a small helper class do to this.

public class DBHelper
    //Validate the user from DB
    public static bool CheckUser(string username, string password)
        DataTable result = null;
            using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["userDbConnectionString"].ConnectionString))
                using (SqlCommand cmd = con.CreateCommand())
                    cmd.CommandType = CommandType.Text;
                    cmd.CommandText = "select password from Users where username = @uname";
                    cmd.Parameters.Add(new SqlParameter("@uname", username));

                    using (SqlDataAdapter da = new SqlDataAdapter(cmd))
                        result = new DataTable();

                    if (password.Trim() == result.Rows[0]["password"].ToString().Trim())
                        //user id found and password is matched too so lets do soemthing now
                        return true;
        catch (Exception ex)
            //Pokemon exception handling

        //user id not found, lets treat him as a guest        
        return false;

    //Get the Roles for this particular user
    public static string GetUserRoles(string username)
        DataTable result = null;
            using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["userDbConnectionString"].ConnectionString))
                using (SqlCommand cmd = con.CreateCommand())
                    cmd.CommandType = CommandType.Text;
                    cmd.CommandText = "select roles from Users where username = @uname";
                    cmd.Parameters.Add(new SqlParameter("@uname", username));

                    using (SqlDataAdapter da = new SqlDataAdapter(cmd))
                        result = new DataTable();

                    if(result.Rows.Count == 1)
                        return result.Rows[0]["roles"].ToString().Trim();
        catch (Exception ex)
            //Pokemon exception handling

        //user id not found, lets treat him as a guest        
        return "guest";

Now whenever the user tries to log in, If the login is successful, keep the username and his Roles in Session variable to use it further, and also we need to Create an authentication ticket for the user (an encypted cookie). So let us do all this in the Button click event of the login page.

protected void Button1_Click(object sender, EventArgs e)
    string roles;
    string username = TextBox1.Text.Trim();
    if (DBHelper.CheckUser(username, TextBox2.Text.Trim()) == true)
        //These session values are just for demo purpose to show the user details on master page
        Session["User"] = username;
        roles = DBHelper.GetUserRoles(username);
        Session["Roles"] = roles;

        //Let us now set the authentication cookie so that we can use that later.
        FormsAuthentication.SetAuthCookie(username, false);

        //Login successful lets put him to requested page
        string returnUrl = Request.QueryString["ReturnUrl"] as string;

        if (returnUrl != null)
            //no return URL specified so lets kick him to home page
        Label1.Text = "Login Failed";

Now before going further, there is one thing to understand. When Forms authentication is being used, whenever the need for authentication arises, the ASP.NET framework checks with the current IPrinciple type object. The user ID and Role contained in this IPrinciple type object will determine whether the user is allowed access or not.

So far we have not written code to push our user specific details in this principle. To do that we need to override a method called FormsAuthentication_OnAuthenticate in global.asax. This method is called each time ASP.NET framework tries to check authentication and authorization with respect to the current Principle.

What we need to do now is to override this method. Check for the authentication ticket (since the user has already been validated and the ticket was created) and then supply this User/Role information in the IPrinciple type object. We can implement our custom Principle type too but to keep it simple, we will simply create a GenericPriciple object and set our user specific details into it [#7 and #8 of our algorithm are covered].

protected void FormsAuthentication_OnAuthenticate(Object sender, FormsAuthenticationEventArgs e)
    if (FormsAuthentication.CookiesSupported == true)
        if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
                //let us take out the username now                
                string username = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;

                //let us extract the roles from our own custom cookie
                string roles = DBHelper.GetUserRoles(username);

                //Let us set the Pricipal with our user specific details
                e.User = new System.Security.Principal.GenericPrincipal(
                  new System.Security.Principal.GenericIdentity(username, "Forms"), roles.Split(';'));
            catch (Exception)
                //somehting went wrong

Now when we run the application, we will see that the authorization mechanism is working as specified in the respective web.config files in perfect unison with our own custom database and authentication logic.

Custom forms authentication article

Note: Running the sample application, looking at code, and debugging the application is strongly recommended to get a full understanding of the above mentioned concepts.

Points of interest

When I came across the requirements of having custom forms authentication, I was rather intimidated. It was partly because I only knew how the ASP.NET default membership provider worked and partly because the hype about how difficult it is to do custom forms authentication. When I sat on it, I found it rather straightforward and easy.

There is one more major area that is also worth looking into to understand the authentication and authorization mechanism completely and that is implementing a custom Membership Provider. Perhaps I will do that in a separate article.


  • June 20. 2012: First version.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Rahul Rajat Singh
Software Developer (Senior)
India India

I Started my Programming career with C++. Later got a chance to develop Windows Form applications using C#. Currently using C#, ASP.NET & ASP.NET MVC to create Information Systems, e-commerce/e-governance Portals and Data driven websites.

My interests involves Programming, Website development and Learning/Teaching subjects related to Computer Science/Information Systems. IMO, C# is the best programming language and I love working with C# and other Microsoft Technologies.

  • Microsoft Certified Technology Specialist (MCTS): Web Applications Development with Microsoft .NET Framework 4
  • Microsoft Certified Technology Specialist (MCTS): Accessing Data with Microsoft .NET Framework 4
  • Microsoft Certified Technology Specialist (MCTS): Windows Communication Foundation Development with Microsoft .NET Framework 4

If you like my articles, please visit my website for more:[^]

  • Microsoft MVP 2015

You may also be interested in...


Comments and Discussions

QuestionForms Authentication deadlock Pin
alexvw30-May-17 5:39
memberalexvw30-May-17 5:39 
Questionencrypted cookie Pin
Member 888171422-Jul-15 20:51
memberMember 888171422-Jul-15 20:51 
AnswerRe: encrypted cookie Pin
JavaDummie22-Dec-15 20:00
memberJavaDummie22-Dec-15 20:00 
QuestionPrincipal.GenericIdentity Pin
Member 888171422-Jul-15 20:04
memberMember 888171422-Jul-15 20:04 
Questiondynamic forms and roles Pin
Member 888171422-Jul-15 20:01
memberMember 888171422-Jul-15 20:01 
Questiondatabase Pin
Member 117392555-Jun-15 22:48
memberMember 117392555-Jun-15 22:48 
AnswerRe: database Pin
Rahul Rajat Singh10-Jun-15 18:15
mvpRahul Rajat Singh10-Jun-15 18:15 
QuestionOne request regarding sql membership Pin
Tridip Bhattacharjee31-Mar-15 21:28
memberTridip Bhattacharjee31-Mar-15 21:28 
QuestionQuestion Pin
Member 112007939-Nov-14 20:33
memberMember 112007939-Nov-14 20:33 
QuestionVery good description Pin
ankursoft31-Oct-14 2:09
memberankursoft31-Oct-14 2:09 
QuestionThank you! Pin
Member 1111232026-Sep-14 9:29
memberMember 1111232026-Sep-14 9:29 
GeneralMy vote of 5 Pin
foosfam13-Sep-14 7:00
memberfoosfam13-Sep-14 7:00 
QuestionCode works perfect Pin
Member 1072690526-Apr-14 16:02
memberMember 1072690526-Apr-14 16:02 
QuestionI could not do the example. Pin
Denilson Ribeiro16-Apr-14 16:04
memberDenilson Ribeiro16-Apr-14 16:04 
QuestionProblem with code Pin
Denilson Ribeiro15-Apr-14 3:09
memberDenilson Ribeiro15-Apr-14 3:09 
GeneralMy vote of 4 Pin
Pratik Bhuva24-Mar-14 3:48
professionalPratik Bhuva24-Mar-14 3:48 
GeneralMy vote of 5 Pin
walterhevedeich7-Jan-14 15:31
professionalwalterhevedeich7-Jan-14 15:31 
GeneralMy vote of 4 Pin
dennisigah16-Nov-13 18:54
memberdennisigah16-Nov-13 18:54 
Questionyou are so great Pin
dinesh143it10-Oct-13 6:04
memberdinesh143it10-Oct-13 6:04 
GeneralMy vote of 5 Pin
vsdaking7-May-13 1:32
membervsdaking7-May-13 1:32 
GeneralMy vote of 5 Pin
mangal deep gupta22-Apr-13 21:14
membermangal deep gupta22-Apr-13 21:14 
GeneralMy vote of 4 Pin
Member 98593628-Apr-13 5:56
memberMember 98593628-Apr-13 5:56 
QuestionLog out Pin
GeethaThozhukat14-Mar-13 5:10
memberGeethaThozhukat14-Mar-13 5:10 
GeneralMy vote of 5 Pin
asp_crazy_guy10-Mar-13 23:05
memberasp_crazy_guy10-Mar-13 23:05 
QuestionThanks And Query !! Pin
Rabbil12-Feb-13 0:29
memberRabbil12-Feb-13 0:29 
AnswerRe: Thanks And Query !! Pin
Rahul Rajat Singh12-Feb-13 17:14
mvpRahul Rajat Singh12-Feb-13 17:14 
The first question where you asked about the process of redirecting the user to their respective page without showing any navigation element, I think you can have a dispatcher class/page which will be called when login is successful. this page will then check the type of the user and send it to the respective location. You will have to write the logic in this page manually by keeping a track of roles and their redirect location.

To answer the second question, the authorization has 2 parts. First having the users with the Roles(which we do in database typically) and configuring the website to run pages based on specific roles.

Now to do the second part, there is one way where I can write code in each page which will check the role and based on that decide whether or not to open the page(imperative approach) but this approach is not very elegant and has maintenance nightmares.

The other way we can do it is by specifying the roles and rights in web.config(declarative approach). This approach is preferable and WSAT is just a tool to put our authorization mappings in web.config. We can do it by hand too but WSAT provides a better abstraction.
Twenty years from now you will be more disappointed by the things that you didn't do than by the ones you did do. So throw off the bowlines. Sail away from the safe harbor. Catch the trade winds in your sails. Explore, Dream. Discover.

GeneralRe: Thanks And Query !! Pin
Rabbil14-Feb-13 1:49
memberRabbil14-Feb-13 1:49 
GeneralRe: Thanks And Query !! Pin
Rahul Rajat Singh17-Feb-13 17:36
mvpRahul Rajat Singh17-Feb-13 17:36 
GeneralRe: Thanks And Query !! Pin
Rabbil18-Feb-13 20:13
memberRabbil18-Feb-13 20:13 
GeneralMy vote of 5 Pin
Savalia Manoj M4-Dec-12 16:43
memberSavalia Manoj M4-Dec-12 16:43 
Generalthanks Pin
insane_rat25-Nov-12 23:44
memberinsane_rat25-Nov-12 23:44 
GeneralMy vote of 5 Pin
mkerrigan16-Nov-12 5:38
membermkerrigan16-Nov-12 5:38 
QuestionApplying Url Rewriting for this Custom Forms Authentication Pin
krishnathota14-Nov-12 22:00
memberkrishnathota14-Nov-12 22:00 
GeneralMy vote of 5 Pin
raisingstar31-Oct-12 9:26
memberraisingstar31-Oct-12 9:26 
QuestionCustom Membership Provder Pin
Member 464125231-Oct-12 1:53
memberMember 464125231-Oct-12 1:53 
AnswerRe: Custom Membership Provder Pin
Rahul Rajat Singh31-Oct-12 2:15
memberRahul Rajat Singh31-Oct-12 2:15 version? Pin
Member 464125230-Oct-12 18:56
memberMember 464125230-Oct-12 18:56 
AnswerRe: .net version? Pin
Rahul Rajat Singh30-Oct-12 20:48
memberRahul Rajat Singh30-Oct-12 20:48 
AnswerArticle of the Day on Microsoft's site Pin
Rahul Rajat Singh2-Oct-12 0:22
memberRahul Rajat Singh2-Oct-12 0:22 
GeneralNice work Pin
abhilash_n27-Sep-12 8:51
memberabhilash_n27-Sep-12 8:51 
AnswerRe: Nice work Pin
Rahul Rajat Singh27-Sep-12 16:13
memberRahul Rajat Singh27-Sep-12 16:13 
Questioncan we store authorization information in sql? Pin
saeedm1217-Aug-12 21:34
membersaeedm1217-Aug-12 21:34 
GeneralMy vote of 5 Pin
Prasad_Kulkarni11-Jul-12 18:29
memberPrasad_Kulkarni11-Jul-12 18:29 
GeneralMy vote of 5 Pin
Md. Marufuzzaman3-Jul-12 10:32
mentorMd. Marufuzzaman3-Jul-12 10:32 
GeneralMy vote of 5 Pin
CK Park3-Jul-12 0:35
memberCK Park3-Jul-12 0:35 
QuestionMy vote of 5 Pin
Member 423686528-Jun-12 13:17
memberMember 423686528-Jun-12 13:17 
GeneralQuestion Pin
stefano.serati27-Jun-12 5:57
memberstefano.serati27-Jun-12 5:57 
AnswerRe: Question Pin
Rahul Rajat Singh27-Jun-12 18:20
memberRahul Rajat Singh27-Jun-12 18:20 
QuestionGood article. Pin
Hiren solanki22-Jun-12 20:39
memberHiren solanki22-Jun-12 20:39 
GeneralMy vote of 5 Pin
parul7722-Jun-12 0:19
memberparul7722-Jun-12 0:19 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.170713.1 | Last Updated 21 Jun 2012
Article Copyright 2012 by Rahul Rajat Singh
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid