ASP.NET forms authentication with roles

Forms authentication does not allow roles authentication. This article explains how to implement it. 

Basic forms authentication

Forms based authentication in ASP.NET is quite useful.  Instead of writing our own authentication processes we can simply change the web.config beneath system.web like so....

<authentication mode="Forms"/>
  <forms
    name="MyWebsiteCookieName"
    loginUrl="/Login.aspx"
    protection="All"
    timeout="180"
  />
</authentication>

  • The authentication mode is set to Forms.
  • A URL is provided so that ASP.NET knows where to redirect people who need to log in.
  • A timeout is specified in minutes.  This is "time since last request" not the "time since login".  If a login is indicated to be persistent (described later) this is ignored.
  • A protection method is specified for the cookie.

Next I wanted to specify a folder to which access is restricted to people who have logged in.  To do this I entered the following code in the web.config file (beneath <configuration>)...

<location path="Members">
  <system.web>
    <authorization>
      <deny users="?"/>
    </authorization>
  </system.web>
</location>

This tells ASP.NET that the path "/Members" (the lead / is always implied) should deny access to all unknown users.  When someone tries to access a page in /Members they will instead be redirected to the login.aspx URL you specified in web.config.

This Login.aspx form should ask for whatever credentials you want (username/password for example) and validate them.  Once they have been validated you only need to execute the following code to have the user redirected back to the page they were originally trying to access...

System.Web.Security.FormsAuthentication.RedirectFromLoginPage(userId, false);

The userId is the unique identifier for the current user (username), and the second Boolean parameter indicates whether this should be a persistent security cookie, or a temporary one (with expiry since last page request), as mentioned earlier.

Roles

It was at this point that I realised I needed a special /Admin folder.  This folder should only be accessed by administrators, and not normal users.  For this I obviously needed roles in the web.config (beneath <configuration>) like so...

<location path="Admin">
 <system.web>
  <authorization>
   <allow roles="Admin"/>
   <deny users="*"/>
  </authorization>
 </system.web>

</location>

Note: The order of the allow/deny is important.  If you deny * (all users) before you allow the Admin role, nobody will have access to the folder.

The problem here though is that you only get roles when the authentication mode="Windows".  For this mode every user needs a valid Windows user account on the server.  Not a good solution.

Luckily I found an interesting article on MSDN.  When you authenticate your user in the Login.aspx form, you should then work out which roles the user belongs to...

if (author.IsAdministrator)
 roles = new string[] {"Admin", "Member"};
else
 roles = new string[] {"Member"};

//1 hour sliding expiry time
Cache.Add(author.UniqueId, roles, null, DateTime.MaxValue,
TimeSpan.FromHours(1), CacheItemPriority.BelowNormal, null);

I have created a string array holding the roles which the user possesses.  These are then stored in the Application[] collection for performance reasons, otherwise we would have to have a DB access every time we wanted to obtain the current user's roles.

Now, because Forms authentication has no concept of Roles these roles will never go into the current user's cookie.  So we must determine what these roles are every time an authentication is executed.  For this we need to go into the global.asax file...

protected void Application_AuthenticateRequest(
  Object sender, EventArgs e)
{
 if (HttpContext.Current.User != null)
 {
  if (HttpContext.Current.User.Identity.AuthenticationType != "Forms")
   throw new Exception("Only forms authentication is supported, not " +
     HttpContext.Current.User.Identity.AuthenticationType);

  System.Security.Principal.IIdentity userId =
    HttpContext.Current.User.Identity;

  //Do we have some roles to retrieve?  If so, replace the user object
  if (Application[userId.Name] != null)
   HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(
                      userId, (string[]) Cache[userId.Name]
   );
 }//user != null
}

This routine checks that the current user != null.  This means that the page is in a protected location.  If this is the case then we use the userId as the key to the Cache[] collection to find a list of roles.  If these roles exist then we reassign the current User with an object we create ourselves, an object which holds a list of roles.

Conclusion

FOR ASP NET DEVELOPMENT, role based security is very useful in web applications.  With a few simple lines of code it is possible to implement role based security for users without a valid Windows login.

 

Share this article!

Follow us!

Find more helpful articles: