Role-Based Authorization With Forms Authentication, Part 2By Darren Neimke and Scott Mitchell
In Part 1 we examined a data model to provide
role-based authorization. We also saw how in order to assign roles to an authenticated user,
we needed to create an event handler for the Application's
event. In this part we'll continue our examination of this event handler.
HttpContextclass encapsulates HTTP-specific information about an HTTP request. This includes response/request headers, server variables, session variables, user information, and so on. Of particular interest is a property called
Current, which returns an instance of the
HttpContextclass that represents the current HTTP request.
Another important property in the
HttpContext class is
which contains security information about the user who made the Web request. The
User property returns a type the implements the
interface, which is our topic of discussion in the following section...
Principals, Roles, and Identities, Oh My!
If you've done any administering of Windows you will be familiar with the concept of Users and Groups. Basically, to access a secured network you must have a user account and that account would be assigned to one or many groups. In .NET these are referred to as Identities and Roles respectively, and they are contained within a
Principalobject. To understand how role based authorization works you need to have an understanding of how these three elements are tied together, and how you can programmatically access their values. Let's look at each element separately.
Identities represent users, and as such, have properties that allow you to obtain information (such as the username) about that user. The classes for working with Identities reside in the
System.Security.Principalnamespace. This namespace contains two classes:
WindowsIdentitythrough which you can determine the properties of a user; and one interface:
IIdentitythat you can use to create custom Identities that can extend the base Identity type to suit needs that are specific to your application.
IIdentity interface contains three properties, the two more interesting
ones for this article being
means you can access the name of the authenticated user using
(Note that with Forms authentication, the value of
User.Identity.Name is the
same value as specified in the name parameter of the
Roles are simply a comma-delimited String of role names that are added to the Principal to associate the current user with one or more roles.
A Principal contains information about the identity and role(s) that the current user is associated with. It is through the Principal that you are able to check the role membership of the current user. In many ways a Principal is the glue that binds identities, roles, and the various other pieces of information that fully describe that Principal to the application.
A Principal is encapsulated by classes found in the
namespace. This namespace contains two Classes:
WindowsPrincipal through which you can
determine the properties of a principal; and one interface
that you can use to define your own custom Principals.
The .NET runtime uses the Principal that is attached to the current thread to gain
information about the identity and roles of a user when handling requests that
require authorization. To programmatically assign your own principal settings you
simply create an instance of the
class passing in an identity object and a comma delimited string of roles for that
identity. The constructor for the
Principal object looks like this:
Putting It All Together
Now that we've had our discussion on Principals, Roles,
HttpContext, and Identities, hopefully the last line of code in the
AuthenticateRequestevent handler looks a little more sensible -
HttpContext.Current.User = New GenericPrincipal(User.Identity, roleListArray). Here, we are assigning to the current HTTP request's
Userprincipal a new
GenericPrincipalbuild up from the user's existing principal plus the set of roles obtained from the database.
There are a number of ways to perform role-based authorization, once you have specified the user's roles. One of the more common approaches is to use the
<authorization>element in the
Web.configfile. With this element, you can restrict or grant access to the Web application based on roles. For example, imagine that you wanted to allow only those playing the Administrator or Moderators roles to a particular Web application or directory in a Web application. To do so, you would simply need to add the following line in your directory's
This allows those who are in the Administrator or Moderators roles, while denying all other users. Membership in roles can also be checked programmatically.
Membership into roles can also be done programmatically using the
method of the
User object. For example, you might have an ASP.NET Web page
that you wanted to allow everyone to access, but the amount of details displayed depended
upon the user's role. Here is some pseudocode that implements such functionality:
As we saw in this article, implementing role-base authorization in a Forms authenticated environment requires that we determine the roles a user belongs to in the Application's
AuthenticationRequestevent's event handler. Once we have assigned the roles to a user's principal, we can grant or deny access to various resources either through the
<authorization>element in the
Web.configfile, or by programmatic means via the
If this topic interests you and you plan on implementing it on your Web site, I would
first encourage you to read with a keen eye an excellent publication from Microsoft:
Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication.
This "best practices" paper discusses in great detail the IIS and ASP.NET security models,
and various techniques for authentication and authorization. Also worth checking out
is How To:
Create GenericPrincipal Objects with Forms Authentication. This article looks at
using role-based authorization with Forms authentication, but instead of hitting the
database at each
AuthenticationRequest event firing, this other approach
stores the authentication information in an encrypted cookie.