Tuesday, June 3, 2008

PrincipalPermission attribute and authorization rules

The ASP.NET pipeline takes an incoming request and processes it through a number of steps. For example the authentication module waits for the AuthenticateRequest event, at which point it inspects the incoming request for an authentication ticket. If an authentication ticket is found, a GenericPrincipal object is created and assigned to the HttpContext.User property.
The HttpContext.User property is a GenericPrincipal object. This GenericPrincipal object has an IIdentity which includes a reference to the authentication ticket. The GenericPrincipal class contains the bare minimum functionality needed by a class that implements IPrincipal – it just has an Identity property and an IsInRole method. When the authentication module creates the GenericPrincipal, it passes in an empty string array to the GenericPrincipal’s constructor. Consequently, any call to IsInRole will always return false. When ASP.NET’s Roles framework is enabled it creates a custom principal object of type RolePrincipal and overwrites the authentication module-created GenericPrincipal object. It does this in order to customize the principal’s IsInRole method to interface with the Roles framework’s API. You can also create a custom IPrincipal object and associate with the User object for role handling.
In this article I will explain how to use the PrincipalPermission attribute available in the System.Security.Permissions namespace to authenticate users using the Identity in your ASP.NET / Winforms application. I have used the details from Scott’s blog for explaining the concept.
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public class UserManager
{
[PrincipalPermission(SecurityAction.Demand, Role = "Admin" , Name="Prajeesh")]
public User AddUser(User user)
{
//Implement the add user code here.
}

[PrincipalPermission(SecurityAction.Demand, Role = "User")]
public void SearchUsersWithName(String userName)
{
//Implement the search users code here.
}
}
By using the PrincipalPermission attribute and decorating with the respective members to the class UserManager we have made sure that the user must be authenticated before this class can be instantiated during a web request. We can also add security demands on the methods of the class and associate the methods with roles. This will make sure that the methods can be invoked for particular roles only.
You can also use the PrincipalPermission attribute with win forms application, but you may need to set the PrincipalPolicy in the constructor of the class as explained below
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public class UserManager
{
private WindowsPrincipal windowsPrincipal;

public UserManager()
{
windowsPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent()); AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
}

[PrincipalPermission(SecurityAction.Demand, Role = "Admin", Name="Prajeesh")]
public User AddUser(User user)
{
//Implement the add user code here.
}

[PrincipalPermission(SecurityAction.Demand, Role = "User")]
public void SearchUsersWithName(String userName)
{
//Implement the search users code here.
}
}
This approach will prevent the methods of the class to be invoked by raising a security exception even if there is a security hole in the presentation layer code.

No comments: