Click here to Skip to main content
Click here to Skip to main content

Insight into Security Model using Principal and Identity Objects in .NET

, 9 Oct 2003
Rate this:
Please Sign up or sign in to vote.
This article introduces the concept behind Principal and Indentity objects in .NET and proposes a security model adopting these objects in a .NET application.

Introduction

The buzz word ‘Security’ strikes me all the time when I think of designing an application. According to me, paramount importance should be given to security of any application, as hackers are always on the move. Security is something an application should possess and not be a feature.

Microsoft.NET as a technology, has given various models/patterns, towards implementing security. The patterns can be customized to suit our requirement and hence is extensible in nature.

Microsoft.NET framework provides certain objects in the name ‘Principal’ and ‘Identity’ objects which would be our primary area of thought. This article mainly focuses on security model by adopting ‘Principal’ and ‘Identity’ objects and proposes a security model for a .NET application.

What are Principal and Identity objects?

Before we proceed any further, it is important for us understand that the very intent of Principal and Identity objects is to authenticate and authorize the end user.

In simple terms, authentication is the process by which the identity of the user is verified and authorization is the process by which access to an application/feature is granted based on the identity.

Identity:

This object stores information about the user. This object encapsulates the name of the user being authenticated. We can relate this object to a data store which stores information (User Name) about a user. Identity objects are of two types.

  • WindowsIdentity: This object encapsulates the Windows login user name and the type of protocol adopted for authentication by Windows. Anytime we need to know the Windows login username, WindowsIdentity objects have the information.
  • GenericIdentity: also stores information about a user, but is used when an application needs to implement custom logon. This object can be created by specifying the User name (usually accepted via custom logon screens) and can be propagated across various application tiers for authorization purposes.

We shall be discussing more in detail about this at a later stage in this article.

Principal:

This object represents the security context for the running process or the AppDomain. Each thread has a context and it holds the principal object. Principal objects encapsulate Identity and the Role/Group membership of a user. Role based security can best be implemented with the help of Principal objects. A Principal object can be created with the help of identity and role of a user. Principal objects are very handy while implementing role based authorization for an application.

Principal objects are of two types:

  • GenericPrincipal: This object encapsulates the identity object and the role. While implementing custom logon with role based authorization, GenericPrincipal objects are to be created.
  • WindowsPrincipal: also stores identity and the Windows group membership of the user. This would very much qualify to implement role based security for an application.

Implementing role based security with Principal objects

The above theory can be well understood by considering a few of the real time scenarios.

Scenario A: Windows authentication (Identity) with roles available from database

Assumption

In this scenario, if roles are found for a user in the database, then the user is a valid user. If a role does not exist for a user in the database, then the user is anonymous and hence should not get access to any feature in the system. Also, there would be an entry for a user in the database only if role(s) are allocated.

In most cases, for an intranet/Windows based application, Windows authentication is preferred with roles being application specific and existing in a data store. Under such circumstances, we would be creating a GenericPrincipal object with Identity as Windows Logon user and roles picked up from the data store for a specific identity. This amounts to Windows identity being used for authentication and GenericPrincipal object built with roles from database used for authorization.

Meaning, we would retrieve the Windows identity, get the user name from the identity object, and query the data store for roles of the user. Once we get the user roles we can construct a GenericPrincipal object and the same can be set to the context/thread.

Now the obvious question would be, who would access the context and how does authorization happen? Let’s consider a hypothetical case wherein we need to grant access to a feature in the application based on the user role.

Authentication

This would be a seamless login from the user’s point of view. The user’s identity can be retrieved with the help of the following code:

Windows application

WindowsIdentity.GetCurrent() method would give us the identity object of the logon user

Imports System.Security.Principal
Module SecurityModule
    Sub Main()
        Dim winIdent As WindowsIdentity = WindowsIdentity.GetCurrent()
        Console.WriteLine(winIdent.Name())
    End Sub
End Module
Web application

By doing the following the identity of the Windows user is obtained

  • Set the authentication mode to Windows and deny authorization to anonymous users in Web.Config file.
  • Implement the WindowsAuthentication_OnAuthenticate event in the Global.asax file. The WindowsAuthenticationEventArgs argument received from this event gives the identity of the Windows user.
<!--Web.Config File Data-->
<authentication mode="Windows"/>
<authorization>
    <deny users="?" />  <!--Deny anonymous users -->
    <allow users="*" /> <!--Allow all users -->
<authorization/>

Global.asax code: The below event is triggered for every request made on the web application.

Sub WindowsAuthentication_OnAuthenticate(ByVal Source As Object, _
                    ByVal e As WindowsAuthenticationEventArgs)
    Dim userIdentity As String
    userIdentity = e.Identity.Name()
End Sub

Authorization

To authorize the users, we got to have roles associated with the identities and hence build the principal object. For the identity obtained from the above global.asax event, query the database and retrieve the roles. Authorization check would be performed in each page of the web application to grant or deny access to a particular feature/page in the application.

The below code explains the complete cycle involved in authorizing a user in accessing an application

Windows application

During application start-up (wherever applicable), for the identity, get the roles from the database accordingly. With the roles and the identity, the principal object needs to be created which would be accessed throughout the application. The below code explains the entire process.

Module SecurityModule
    Public genPrincipal As GenericPrincipal

    Sub Main()
        Dim ident As WindowsIdentity = WindowsIdentity.GetCurrent()
        Dim roles() As String

        roles = <retrieve from database>
        genPrincipal = New GenericPrincipal(ident, roles)
    End Sub
End Module

The above generic principal object would be accessed in each of the Windows forms in deciding whether to grant or deny access to the requested feature, as shown below:

Private Sub Form1_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load

    If genPrincipal.IsInRole("Managers") = False Then
        MessageBox.Show("You do not have access to this form")
    End If
End Sub
Web application

For a web application, before we proceed with authentication check, we got to build the principal object. And, for the web page to access this principal object, the same has to be persisted in the HTTP context. The code below explains this process:

In WindowsAuthentication_OnAuthenticate event, get the roles for the identity obtained. This completes the authentication bit. The next event to get fired just after this is the Application_AuthenticateRequest wherein the principal object needs to be built. Hence the identity and the roles obtained in WindowsAuthentication_OnAuthenticate event have to be persisted for Application_AuthenticateRequest to build the principal object. The same is performed by creating an authentication ticket out of identity-roles, and send as cookie. Now the Application_AuthenticateRequest event can access the cookie and build the Principal object as shown below

Sub WindowsAuthentication_OnAuthenticate(ByVal Source As Object, _
        ByVal e As WindowsAuthenticationEventArgs)
    
    'Note that since IIS has already performed 
    'authentication, the provided identity is used.

    Dim userIdentity As String
    Dim userRoles As String
    Dim formsAuthTicket As FormsAuthenticationTicket
    Dim httpcook As HttpCookie
    Dim encryptedTicket As String

    userIdentity = e.Identity.Name()
    useRoles =<Retrieve from Database>

    formsAuthTicket = New FormsAuthenticationTicket(1, _
        e.Identity.Name(), _
        DateTime.Now,DateTime.Now.AddMinutes(60), _
        False, userRoles)

    encryptedTicket = FormsAuthentication.Encrypt(formsAuthTicket)

    httpcook = New HttpCookie("authCookie", encryptedTicket)
    Response.Cookies.Add(httpcook)
End Sub
Sub Application_AuthenticateRequest(ByVal sender As Object, _
            ByVal e As EventArgs)

    ' Fires upon attempting to authenticate the user
    Dim formsAuthTicket As FormsAuthenticationTicket
    Dim httpcook As HttpCookie
    Dim genIdentity As GenericIdentity
    Dim roles() As String
    Dim genPrincipal As GenericPrincipal

    httpcook = Context.Request.Cookies("authCookie ")
    formsAuthTicket = FormsAuthentication.Decrypt(httpcook.Value)

    genIdentity = New GenericIdentity(formsAuthTicket.Name())
    roles = formsAuthTicket.UserData.Split("|") 'if more than one role

    genPrincipal = New GenericPrincipal(genIdentity, roles)

    'The principal object thus created would be accessed 
    'in the ‘application pages before allowing access 
    'to the individual functionality 
    HttpContext.Current.User = genPrincipal
End Sub

Now after the Principal object has been set, let’s move over to the web page to authorize the user. In the Form_Load event of the web page (PageA.aspx), let’s say, we have to grant access only to users of role ‘Managers’. The below code would perform the authorization check

Private Sub Page_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load

    Dim genPrincipal As IPrincipal

    ' Access the principal object from HTTPContext
    genPrincipal = HttpContext.Current.User

    If genPrincipal.IsInRole("Managers") = False then
        Response.Write("You do not have access to this Page.")
        ' Now the controls on the form can be hidden
        ' or the user can be redirected 
        ' to a different page
        ' < Code to implement the above goes here >
    End if
End Sub

The above would not give access to PageA.aspx, to any user who does not belong to ‘Managers’ role/group.

In all, this security model best suits for applications which need to implement role based security with roles as defined by the application and authentication performed by Windows.

Scenario B: Custom authentication (Identity) with roles available from database

This scenario best suits applications which have users as well as roles defined in the application. Such applications will have logon page/form which accepts username and password and performs authentication. The same code as explained in scenario A except for authentication mechanism can be adopted in this scenario as well. The authentication would follow with user ID and password being validated against a data store and continues to build the generic principal object with the help of GenericIdentity and roles retrieved from the database.

Scenario C: Windows authentication (Identity) with Windows group membership as roles

This scenario best suits applications which depend on Windows for identity and roles. Identity would be the Windows username and the role would be the group membership of the Windows user. The concept of role based security remains the same and is similar to the code as mentioned in Scenario A. Instead of creating GenericPrincipal object, we got to be creating WindowsPrincipal object, by supplying the WindowsIdentity. Also, there is no need to get ‘roles’ from a data store as we are depending on Windows group membership for roles. The check that would be performed in each page/form remains the same.

Scenario analysis

In the above scenarios, all we are doing is building the principal objects which consists of identity and roles. The pages/forms need not worry about building the Principal objects. They just need to perform ‘IsInRole’ checks depending on the authorization rules as set by the application.

This demonstrates the clear segregation between authentication and authorization when Identity and Principal objects are adopted for implementing security. Also, throughout the life of the application, we are dealing with objects encapsulating identity, roles and are persisted across.

Conclusion

The scenarios just demonstrate the usage of Principal and Identity objects. They do not imply any rules on its usage. The scenarios were chosen as a means to understand the concepts better. In all, the Principal and Identity objects provide a means to implement security for any application in .NET.

Using the code

The code snippets mentioned throughout this article is part of the source code available for download with this article. On downloading the source code (Zip File), extract the same to web folder (wwwroot) to successfully open the solution. In the IIS Settings for the web application, make sure anonymous access is unchecked in Directory Security tab.

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

Share

About the Author

* Sandeep Alur
Web Developer
India India
Sandeep Alur, is from Bangalore, India. He works for Wipro Technologies, one of the leading software services company. His aspiration is to contribute his learnings from his experience,to the developer community. You can find quite a few of his technical articles published at DevelopersDex portal.
 
He is also a Microsoft Certified Solution Developer(MCSD.NET) in .Net

Comments and Discussions

 
GeneralNice Article - Get your 5 PinmentorKunalChowdhury20-May-10 18:07 
GeneralGood Work PinmemberRajeshCR30-Jan-05 20:00 
GeneralCookie Re-created Everytime PinsussAnonymous1-Jul-04 9:21 
GeneralRe: Cookie Re-created Everytime Pinmembercindyrod7-Aug-05 17:30 
GeneralRe: Cookie Re-created Everytime PinmemberPiddy26-Mar-06 17:37 
GeneralRole Hierarchies Pinmembergmgerstner8-Apr-04 10:35 
GeneralRe: Role Hierarchies PinsussAnonymous6-May-04 7:14 
GeneralRe: Role Hierarchies Pinmembergmgerstner10-May-04 4:07 
GeneralRe: Role Hierarchies PinmemberTonyS31-May-05 15:29 
Generalwindows authentication thru a web form PinmemberBharat Biyani23-Jan-04 0:18 
GeneralRe: windows authentication thru a web form PinsussAnonymous23-Aug-05 14:13 
GeneralQuestions on ACLs and Sub-Groups PinmemberFull Meat25-Nov-03 20:43 
GeneralRe: Questions on ACLs and Sub-Groups PinmemberJan Seda (MS)19-Dec-04 22:54 
AnswerRe: Questions on ACLs and Sub-Groups Pinmemberanon2356-Sep-06 12:51 
QuestionHow can we log off when using windows authentication ? Pinmemberdfranco_miami@msn.com20-Nov-03 10:24 
AnswerRe: How can we log off when using windows authentication ? Pinmember* Sandeep Alur20-Nov-03 19:21 
AnswerRe: How can we log off when using windows authentication ? PinmemberFull Meat25-Nov-03 20:23 
AnswerRe: How can we log off when using windows authentication ? Pinmembermkamoski120-Jul-04 8:59 
GeneralWeb Authentication Pinmemberabu-khiran15-Oct-03 19:21 
GeneralRe: Web Authentication Pinmember* Sandeep Alur15-Oct-03 22:27 
GeneralRe: Web Authentication PinsussAnonymous27-Dec-03 7:36 
GeneralNicely Done Pinmemberjackm15-Oct-03 2:22 
GeneralCool! Pinmemberworldspawn12-Oct-03 13:42 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141030.1 | Last Updated 10 Oct 2003
Article Copyright 2003 by * Sandeep Alur
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid