I create a lot of web-based back office applications for small businesses such as travel agencies, real estate companies, etc. I also consult on a lot of such back office applications.
One particular important area within these applications is security. Typically these applications will use role-based security to give users different privileges within the application based on their roles.
Sometimes the administrative area is placed within a special directory within the application and you find something in the web.config like this:
<location path="myadmindirectory">
<system.web>
<authorization>
<allow roles="Administrators" />
<deny users="*" />
</authorization>
</system.web>
</location>
This basically says only users authenticated and subscribing to the “Administrators” role have access to this directory and nobody else.
Typically, I find that this is all the security on these pages, and my question is then, what if by some chance this setting in the web.config is lossed? Anyone can get into these pages. I look at this as more of living in a guard-gated community. Certainly it is nice, but I lock my doors, too!
As another level of security on these pages, I like to put PrincipalPermission Attributes on the admin page classes themselves so that we have another layer of security. You can do this on a base admin page class for which admin pages are derived for efficiency if it works for you.
[PrincipalPermission(SecurityAction.Demand, Authenticated=true, Role = "Administrators")]
public class AdminPage : System.Web.UI.Page
{
...
}
If the user attempting to access the page is not in the role “Administrators”, a security exception is invoked.
If two different roles can access this page, you can do a logical OR on the roles by including two attributes. (Don't forget to change your web.config to allow “Agents“ in the directory)
[PrincipalPermission(SecurityAction.Demand, Authenticated=true, Role = "Administrators")]
[PrincipalPermission(SecurityAction.Demand, Authenticated=true, Role = "Agents")]
public class AdminPage : System.Web.UI.Page
{
...
}
The cool thing is that you can get more granular than just at the page class level. You can add these PrincipalPermission attributes to methods as well. In the below example, only administrators can add a user, whereas both Administrators and Agents can display a user.
[PrincipalPermission(SecurityAction.Demand, Authenticated=true, Role = "Administrators")]
[PrincipalPermission(SecurityAction.Demand, Authenticated=true, Role = "Agents")]
public class AdminPage : System.Web.UI.Page
{
...
[PrincipalPermission(SecurityAction.Demand, Authenticated=true, Role = "Administrators")]
public void AddUser()
{
}
public void DisplayUser()
{
}
...
}
If a security exception is raised by the application, you can handle it locally on the page level via Page_Error, or if you want, handle it globally within the Global.asax.cs within Application_Error.
There are ways to do this in code as opposed to attributes, which I leave for another time.