Roles for User property in HTTP Current Context

While I was dealing with some potential vulnerability issue affecting to some of "my" MVC 5.0 application in .Net Framework 4.5 and coming from a wrong management of user roles, it turns out that I didn't remember clearly how role management was related to User principal or even, where roles came from in order to IsInRole method were able to work properly to check roles for users. So, let me add this post as a reminder to clarify and shed light on this.


What is user property of Current HTTP Context?

System.Web.HttpContext.User property gets or sets security information for the current HTTP request context.

Before going ahead with User property, let me reminder you some important information about the HttpContext class. It encapsulates all the information for a given HTTP request and is created by the ASP.Net run-time whose code is mainly stored in the system.web assembly. Here are some great articles explaining the ASP.Net application life cycle and the ASP.Net page life cycle. See the picture below for a quick reference:

The value for the User property in HttpContext must be an instance class implementing System.Security.Principal.IPrincipal interface:

Properties

Identity -> Gets the identity of the current principal.

Methods

IsInRole(String) -> Determines whether the current principal belongs to the specified role passed as input param.


Where do roles come from?

To begin with, "Role Manager" feature was added in ASP.Net 2.0 and provides basic functionality to create IPrincipal-based objects linked to roles. Its main goal is to make easier for developers to provide authorization based on roles.

The "Role Manager" feature has a static class Roles that can be used as an easy way to access all the functionality provided by this feature. Basically, it provides public properties and methods that expose data from configuration (<roleManager /> in web.config).

So, getting straight to the point, when "Role Manager" is enabled (enabled attribute set to true in <roleManager /> node), early during the request lifecycle the RoleManagerModule HttpModule creates and assigns a RolePrincipal instance to the User property of the CurrentHttpContext. This task occurs during the PostAuthenticateRequest event.

The RolePrincipal class implements the IPrincipal interface and besides, provides additional properties and methods. For instance, not only it implements the IsInRole method for determining if a given user belongs to a specific role but a new method for returning the complete list of roles for a user as well (GetRoles method). It could be very useful in some cases.

Therefore, in this situation ("Role Manager" enabled), roles and related information are obtained by means of the RolePrincipal class.

To enable "Role Manager", the web.config file must be configured accordingly as explained in detail in Roles class documentation. Basically, all you have to do is using the <roleManager /> node under <system.web /> node in web.config and set the attribute enabled to true. There are other properties you can use to set up further features but it is not the goal of this post. Take a deeper look to the references and official documentation if needed.

How do RolePrincipal class deal with roles?  

As said before, the RolePrincipal class exposes the security identity for the current HTTP request and additionally performs checks for role membership. In addition to this, if CacheRolesInCookie property is set to true, then the RolePrincipal object manages the cached list of roles within a cookie and looks up role membership for the current user in the cached list first, and if not present, calls the proper methods in the linked RoleProvider class. If CacheRolesInCookie is false, the RolePrincipal object always looks up role membership using the RoleProvider.

Therefore, RolePrincipal gets roles primarily from RoleProvider and optionally stores and retrieve those roles from a cookie due to performance considerations. For instance, both the IsInRole and GetRoles methods from RolePrincipal rely on the RoleProvider associated to the RolePrincipal to carry out the work of determining belonging to roles or return the list of roles for a user.

How to configure "Role Manager" to use a given RoleProvider?

In the web.config file you can add providers as displayed in the code sample below:

<roleManager defaultProvider="CustomRoleProvider" 
      enabled="true"
      cacheRolesInCookie="true"
      cookieName=".ASPXROLES"
      cookieTimeout="30"
      cookiePath="/"
      cookieRequireSSL="false"
      cookieSlidingExpiration="true"
      cookieProtection="All" >
      <providers>
        <clear />
        <add
          name="CustomRoleProvider"
          type="YourNameSpace.CustomRoleProvider" />
      </providers>
</roleManager>

Notice the <providers /> node and the <add /> section within it. You can add a predefined provider or even create your own custom provider as done above. This provider will be the responsible for dealing with roles.

How to implement a custom RoleProvider?

Eventually, if you decide to implement your own provider you have different options. You can implement it from the scratch (see here for more information) or you can do it easier and simpler by inheriting from an existing RoleProvider and then overriding the methods you need to:

public class CustomRoleProvider : System.Web.Security.RoleProvider
{
        public override string[] GetRolesForUser(string username)
        {
            // To do
        }

        public override bool IsUserInRole(string username, string roleName)
        {
           // To do
        }

        // To do
}

The details of the implementation are not the most important and can be omitted here. You can retrieve the roles from a database or your custom store by using the methods from your custom role provider. The details of the implementation are up to you and depends on your requirements.


To summarize, whenever the IsInRole method of the User principal object is called for the current HTTP request, the associated RolePrincipal object will return the boolean result based on the comparison between the input param and the list of roles returned from the RoleProvider for the authenticated user.

More References

Professional ASP.NET 3.5 Security, Membership, and Role Management with C# and VB

 

 

 

 

 

 

 

 

 

Add comment