Click here to Skip to main content
15,861,125 members
Articles / Web Development / ASP.NET
Article

Custom Authentication provider by implementing IHttpModule, IPrincipal and IIdentity

Rate me:
Please Sign up or sign in to vote.
4.55/5 (41 votes)
2 Nov 20033 min read 357K   10.5K   159   41
An article on writing Custom Authentication provider in ASP.NET

Image 1

Introduction

For a real-world Enterprise application, security plays an important role. Forms-based authentication is a popular technique used by many Web sites. With ASP.NET, writing forms authentication is like a breeze. Forms Authentication provider in ASP.NET exposes cookies-based authentication services to applications. But for some of the applications due to the nature of the security requirements, Forms Authentication provider is not a very good fit. Writing your own Custom Authentication provider offers a solution for such applications. With very little code and effort, you can have a role-based authentication system that is platform-agnostic.

Background: Forms Authentication provider - Not a good fit

Lets take a scenario - An application wants to store the following information for a User:

  1. Username
  2. User Primary key (primary Key of the User table)
  3. E-mail
  4. User Full name
  5. Is user an Administrator
  6. Is user authenticated
  7. Roles for the User

Forms Authentication provider uses the FormsAuthenticationModule, FormsIdentity, FormsAuthenticationTicket and GenericPrincipal classes. The application can store the UserName and roles information in the FormsAuthenticationTicket. But this application needs to store other information, which cannot be done using FormsAuthenticationTicket or FormsIdentity class. To achieve this we can create a custom Identity class by implementing IIdentity interface. However, on each Request application needs to get the User's data from the underlying data source (SQL Server, XML , LDAP ) and create a CustomIdentity object with all the details. The code in Login page will be something like this (Listing 1):

Listing 1 - Login.aspx

C#
//Validate User
//SecurityManager is a helper class of your application
if(SecurityManager.ValidateLogin(txtUserName.Text, txtPassword.Text))
{
    //Get a CustomIdentity object with all the details 
    //for the authenticated user
    CustomIdentity identity = SecurityManager.GetUserIdentity(
          txtUserName.Text);
    if(identity != null && identity.IsAuthenticated)
    {
        //Get user Roles
        ArrayList roles = SecurityManager.GetUserRoles(txtUserName.Text);
        //Create a CustomPrincipal object
        CustomPrincipal newUser = new CustomPrincipal(identity, roles);
        Context.User = newUser;
        //Redirect user to the requested page
        FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, False);
    }
}

The code in Global.asax will be something like this (Listing 2):

Listing 2 - Global.asax.cs

C#
//Implement an Authentication Request Handler to Construct
// a GenericPrincipal Object
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    HttpCookie authCookie = Request.Cookie[
             FormsAuthentication.FormsCookieName];
    if(authCookie != null)
    {
        //Extract the forms authentication cookie
        FormsAuthenticationTicket authTicket = 
               FormsAuthentication.Decrypt(authCookie.Value);
        // Create an Identity object
        CustomIdentity id = SecurityManager.GetUserIdentity(authTicket.Name);
        //Get user Roles
        ArrayList roles = SecurityManager.GetUserRoles(txtUserName.Text);
        //Create a CustomPrincipal object
        CustomPrincipal newUser = new CustomPrincipal(identity, roles);
        Context.User = newUser;
    }
}

For more details on the above example please visit MSDN - How To: Implement Iprincipal

This approach works fine for some applications but think of the unnecessary overhead it has in retrieving the user details on each Request. If your application can live with such a design than be it. But for some of the very interactive, performance savvy applications, this approach is not suitable. Here, writing a Custom Authentication provider serves the purpose.

Custom Authentication module

Implementing the IHttpModule interface allows you to include custom events that participate in every request made to your application. Custom Authentication can be achieved by implementing IHttpModule and writing a Custom HttpModule. I have created a Custom Authentication provider by implementing IHttpModule. My CustomAuthentication provider has the following classes:

  1. CustomIdentity.cs - Implements IIdentity and contains User details (you can change it as per your requirements).
  2. CustomPrincipal.cs - Implements IPrincipal and represents a Custom Principal object (you can change it as per your requirements).
  3. CustomAuthenticationModule.cs - Implements IHttpModule and handles AuthenticateRequest event of the HttpApplication.
  4. CustomAuthentication.cs - Provides static helper methods like creating a encrypted Authentication string etc.
  5. CustomEncryption.cs - Utility class for encrypting and decrypting authentication string (you can change it to implement your own encryption algo).

    The Custom Authentication provider needs the following entries in Web.Config appSettings section:

Listing 3 - Web.config

XML
<!-- Entries required for CustomAuthenticationModule -->
<appSettings>
    <!-- Parameter for the Login page URL (Required) -->
    <add key="CustomAuthentication.LoginUrl" value="/Login.aspx" />
    <!-- Parameter for the Authentication cookie Name (Required) -->
    <add key="CustomAuthentication.Cookie.Name" value=".CUSTOM_AUTH" />
    <!-- Parameter for Timeout for Cookie expiration in minutes 
       (Optional- persist cookie across browser sessions) -->
    <add key="CustomAuthentication.Cookie.Timeout" value="2" />
</appSettings>

Sample Application

There is a sample application, which uses this CustomAuthentication module. To add a custom HttpModule, add the following entries to the Web.config file:

Listing 4 - Web.config

XML
<!-- Add a Custom Authentication module -->
<httpModules>
    <add name="CustomAuthenticationModule" 
       type="CustomSecurity.CustomAuthenticationModule, CustomSecurity" />
</httpModules>

Add the required entries for CustomAuthenticationModule as given above in Listing 3. Please see the required code in login page. This is the only code you need to write (Listing 5).

Listing 5 - Login.aspx

C#
//Write your own Authentication logic here
if(this.username.Text != "" && this.password.Text !="")
{
    //Write your own code to get the User Roles
    ArrayList roles = new ArrayList();
    roles.Add("Manager");

    if(this.username.Text == "superuser")
        roles.Add("Administrator");

    roles.Add("ITUser");

    //Convert roles into pipe "|" separated string
    System.Text.StringBuilder strRoles = new System.Text.StringBuilder();
    foreach(string role in roles)
    {
        strRoles.Append(role);
        strRoles.Append("|");
    }

    //Create a CustomIdentity object
    CustomIdentity userIdentity = new CustomIdentity(this.username.Text, 
        1, true, true, this.username.Text, 
        "someuser@some.com", strRoles.ToString());
    //Create a CustomPrincipal object
    CustomPrincipal principal = new CustomPrincipal(userIdentity, roles);
    Context.User = principal;
    //Redirect user
    CustomAuthentication.RedirectFromLoginPage(userIdentity);
}

You can access the CustomIdentity and CustomPrincipal object in any aspx page or in any class of middle layer of your application using the following code (Listing 6):

Listing 6 - Home.aspx

C#
//Get the CustomIdentity in aspx pages from the HttpContext
this.user1.Text = ((CustomIdentity)Context.User.Identity).UserFullName;

//Get the CustomIdentity in any class in middle layer from the Thread
this.user2.Text = ((CustomIdentity)
    Thread.CurrentPrincipal.Identity).UserFullName;
role.Text =  Thread.CurrentPrincipal.IsInRole("Administrator").ToString();

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


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionSource Code Pin
Member 1258366231-Mar-17 20:57
Member 1258366231-Mar-17 20:57 
GeneralCan you specify a license for this code. Pin
hhearst24-Apr-11 10:07
hhearst24-Apr-11 10:07 
GeneralMy vote of 5 Pin
WestieBoy14-Feb-11 21:14
WestieBoy14-Feb-11 21:14 
GeneralMVC Pin
san.diego18-Nov-10 23:13
san.diego18-Nov-10 23:13 
GeneralNice Job Pin
Hamed J.I25-Sep-10 22:25
Hamed J.I25-Sep-10 22:25 
QuestionAuthentication across subdomains and localhost? Pin
atlas_usr11-May-10 15:19
atlas_usr11-May-10 15:19 
GeneralUse with standard Authorization module Pin
Angus-AU8-Dec-09 15:50
Angus-AU8-Dec-09 15:50 
GeneralRe: Use with standard Authorization module Pin
reginaldo19829-Dec-09 6:30
reginaldo19829-Dec-09 6:30 
GeneralRe: Use with standard Authorization module Pin
Angus-AU10-Dec-09 13:17
Angus-AU10-Dec-09 13:17 
GeneralRequest Error Pin
Member 250733518-Jul-09 0:23
Member 250733518-Jul-09 0:23 
GeneralRe: Request Error Pin
serjoka28-Sep-09 1:51
serjoka28-Sep-09 1:51 
GeneralRe: Request Error Pin
Member 250733529-Sep-09 3:44
Member 250733529-Sep-09 3:44 
Questionmissing cookies? Pin
TheMountain12-Nov-08 10:04
TheMountain12-Nov-08 10:04 
GeneralAutoPostBack="True" Pin
feifei_200520-Dec-07 16:06
feifei_200520-Dec-07 16:06 
GeneralRe: AutoPostBack="True" Pin
hhxs9-Jul-09 22:07
hhxs9-Jul-09 22:07 
GeneralRe: AutoPostBack="True" Pin
THE SK22-Feb-11 3:51
THE SK22-Feb-11 3:51 
Generaldon`t download! Pin
feifei_200518-Dec-07 23:52
feifei_200518-Dec-07 23:52 
QuestionAuthentication Mode Pin
sergiosulpizio@yahoo.it19-Feb-07 0:51
sergiosulpizio@yahoo.it19-Feb-07 0:51 
AnswerRe: Authentication Mode Pin
brharsh14-Jun-07 11:13
brharsh14-Jun-07 11:13 
AnswerRe: Authentication Mode Pin
Sergio Pereira19-Jul-07 6:08
Sergio Pereira19-Jul-07 6:08 
GeneralRe: Authentication Mode Pin
Byttencourt25-Nov-09 0:14
Byttencourt25-Nov-09 0:14 
QuestionAnd Logout? Pin
s.belia14-Mar-06 21:56
s.belia14-Mar-06 21:56 
AnswerRe: And Logout? Pin
boonkerz10-Sep-06 9:47
boonkerz10-Sep-06 9:47 
GeneralRe: And Logout? Pin
BostonIdiot4-Oct-08 7:22
BostonIdiot4-Oct-08 7:22 
Wouldn't removing the cookie serve as logging out?

I am just guessing....
GeneralRe: And Logout? Pin
Vishwamr150625-Nov-09 3:51
Vishwamr150625-Nov-09 3:51 

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.