When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article

ASP ASP.NET ASP FAQs Message Board Feedback
 
Print this Page!
Published: Wednesday, August 27, 2003

Role-Based Authorization With Forms Authentication

By Darren Neimke and Scott Mitchell


For More Information...
For more information on forms-based authentication in ASP.NET be sure to read Dissecting Forms-Based Authentication.

This article was written in 2003 and is applicable to ASP.NET version 1.x. Starting with ASP.NET version 2.0, Microsoft introduced the Membership and Roles frameworks, which greatly simplify creating and managing user accounts and roles. Refer to Examining ASP.NET's Membership, Roles, and Profile and these Security Tutorials for more information on using Membership and Roles.

Introduction


In Web applications, typically there exist certain parts of the site that only certain individuals, or groups of individuals, can access. For example, imagine an intranet Web site used to administer the content on a company's public Internet Web site, where the public Web site lists products sold by the company. From the administrative site, all company employees might be able to make minor changes to the products' descriptions, quantity, and other such non-essential information. However, perhaps only a subset of trusted employees might be able to change the products' prices. And even a smaller subset of employees would be able to add new products or delete existing products from the database.

- continued -

To handle such a hierarchy of capabilities, a traditional security model to use is to divide users into roles, and then to assign permissions to various resources on a role-by-role basis. For example, our fictional company's administrative Web site might be setup so that the President, CEO, and CIO are made "Administrators" of the product database, and have access to change the product database via the online interface in any way they desire. The top-level managers might be added to the Price Changer role, meaning they can change the prices of existing products, while all other company employees were inserted into the Minor Updates role. Such a security model is typically referred to a role-based authorization model, as the authorization users enjoy is based upon the role they play within the system.

In this article we will examine how to utilize role-based authorization in an ASP.NET Web application using Forms authentication. Specifically, we'll examine the data model needed for implementing roles, we'll see how to determine what roles a given user belongs to, and then how to restrict (or grant) access to resources based on a user's roles.

A Quick Security Overview


When thinking or talking about security, there are two fundamental underpinnings which are central to understanding role-based authorization and security models in general. These two concepts are:

  • Authentication - authentication is the act of identifying who a user is. In Web applications, this is typically done by having the user provide some credentials, such as a username and password.
  • Authorization - authorization is the act of granting or denying access to a resource based upon the user attempting to access the resource.

Before we can discuss role-based authorization, we must first think about how we will authenticate our users. ASP.NET provides three methods for authentication:

  1. Windows Authentication - Useful when working on an intranet, where every user who needs to be authenticated has a Windows account on the Web server's domain,
  2. Passport Authentication - Uses Microsoft's Passport service, and
  3. Forms Authentication - Prompts the user for a set of credentials (typically username and password).

This article will focus on using role-based authorization with Forms authentication. (If you are unfamiliar with Forms authentication, be sure to check out Darren Neimke's excellent article, Using Forms Authentication in ASP.NET.)

Getting Role-Based Authorization Working - the First Steps


In order to provide role-based authorization, we need some way to model the roles and the users that participate in these roles. Typically, when using Forms authentication a user is modeled as a row in a database table. Each user usually contains information pertinent to the Web application, including the user's credentials (i.e., their username and password).

So, before we can get started at looking at the code necessary for implementing role-based authorization, we need to provide a data model. Our data model will consist of three related tables:

  • Users - each record in this table models an individual user. The pertinent fields in this table include UserID (a unique identifier for each user), Username, and Password.
  • Groups - each record in this table models a group. The Groups table's pertinent fields are GroupID and Name. Groups are the classifications to which users can be assigned. For example, a Web application might have groups like: Administrators, Moderators, Testers, and so on.
  • Roles - the Roles table models the many-to-many relationship between Users and Groups. Specifically, a role maps a user to a group. The Roles table needs only two fields: UserID and GroupID.

An example database might be as follows:

Users
UserIDUsernamePassword
1Bobpassword1
2Scottpassword2
3Jisunpassword3
4Sampassword4
5Johnpassword5
Groups
GroupIDName
1Administrators
2Moderators
3Testers
4Premium Members
Roles
UserIDGroupID
11
22
23
34
43
44

In this sample database there are five users and four groups. Bob is in the Administrator role, Scott is in the Moderators and Testers roles, Jisun is in the Premium Members role, Sam is in the Testers and Premium Members roles, and John is not in any roles.

Determining What Roles a User Is In


The .NET Framework contains an HttpApplication class that represents an ASP.NET Web application. This class has a number of events that can fire during various times of the Web application's lifecycle. The invent we're interested in is the AuthenticateRequest event, which fires each time when the ASP.NET security module has established the identity of a user. We can write an event handler for this event in the Global.asax file. In this event handler we need to determine what roles this user belongs to.

The following shows the code for the AuthenticateRequest event handler:

Sub Application_AuthenticateRequest(sender As Object, e As EventArgs)
    If Request.IsAuthenticated Then
        'Determine this user's roles
        Dim reader As SqlDataReader = _
              SqlHelper.ExecuteReader(connection string, _
              CommandType.StoredProcedure, "rolesForUser", _
              New SqlParameter("@Username", User.Identity.Name))

        ' Create an array of role names
        Dim roleList As New ArrayList
        Do While reader.Read()
            roleList.Add(reader("Name"))
        Loop

        'Convert the roleList ArrayList to a String array
        Dim roleListArray As String() = roleList.ToArray(GetType(String))

        'Add the roles to the User Principal
        HttpContext.Current.User = _
             New GenericPrincipal(User.Identity, roleListArray)
    End If
End Sub

Let's examine this code sample line-by-line. The first line checks to see if the user is an authenticated user. That is, if we are dealing with an anonymous Web user, there's no point in hitting the database to determine what roles the anonymous user belongs to. By the data model I presented earlier, only users that exist in the database can be assigned roles.

If the user has been authenticated, then the Request.IsAuthenticated property will return True, and the code inside the If statement will execute. Next, the code uses the Microsoft Data Access Application Block to execute the stored procedure titled rolesForUser, passing in the authenticated user's name as the value for the @Username parameter. (If you are unfamiliar with the MS Data Access Application Block, it is a free assembly from Microsoft that can be used to encapsulate a lot of the extra complexity involved in making database calls. For more information, be sure to read: Examining the Data Access Application Block.)

The results of the stored procedure - whose syntax we'll examine shortly - are then inserted into an ArrayList. The ArrayList is then converted into a String array using the ToArray() method. Finally, the current user's User context is reassigned to a new GenericPrincipal instance with the user's existing Identity and the set of roles. (Don't worry if you do not yet understand the syntax here or the purpose of the code - we'll discuss this last line of code in more detail in the next section.)

The rolesForUser stored procedure is fairly straightforward - it simply takes in a single parameter (the username to search on) and then returns the list of roles the user belongs to.

CREATE PROCEDURE rolesForUser 
(
   @Username   varchar(50)
)
AS

SELECT G.Name
FROM Roles R
   INNER JOIN Groups G ON
      R.GroupID = G.GroupID
   INNER JOIN Users U ON
      R.UserID = U.UserID AND U.Username = @Username

In Part 2 we'll examine the code for this event handler in more detail, specifically examining the HttpContext class and Principals, Roles, Groups, and Users!

  • Read Part 2!



  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article