ASP.NET Routing and Authorization

I got a great question on Tuesday night at the .NET Developer Network where I was talking about some of the upcoming ASP.NET features such as MVC and Dynamic Data. The question was, how do I go about preventing access to pages when using the new ASP.NET Routing features.

The first thing I would say is that ASP.NET routing as it stands right now isn't optimised for use in webforms applications - ie development has been focused on supporting Dynamic Data and the MVC framework. That means you're breaking new ground and you pretty much have to do everything for yourself. We'll add further support in the fullness of time but back to the question...

If you use the standard "access rules" technique by adding a web.config to a particular folder to restrict access:

 <configuration>
    <system.web>
        <authorization>
            <allow roles="Admin" />
            <deny users="*" />
        </authorization>
    </system.web>
</configuration>

This will prevent someone from directly hitting the URL but it wont prevent access via ASP.NET Routing. eg for my Routing application below, the web.config (above) in the SimpleViews folder will prevent me directly accessing Default.aspx via the URL https://localhost/Routing/SimpleViews/Default.aspx but not via the "Routing" URL https://localhost/Routing/Default. How do we deal with that?

Picture1

Chris and Phil got there before me so I recommend reading those posts but essentially we would add an additional check as part of the route handler that checks whether the current user is authorised to view the requested path by calling UrlAuthorizationModule.CheckUrlAccessForPrincipal(). Thus, my code that I originally posted back here could be modified along the following lines:

 public class MEOSimpleRouteHandler : IRouteHandler
{
  public IHttpHandler GetHttpHandler(RequestContext requestContext)
  {
    string viewName
      = requestContext.RouteData.GetRequiredString("ViewName");

    viewName =
      viewName.ToLower() == "home" ? "default" : viewName;

    return GeneratePage(viewName, requestContext);
  }

  private IHttpHandler GeneratePage(string VN, RequestContext RC)
  {
    string virtualPath
      = string.Format("~/SimpleViews/{0}.aspx", VN);

    if (UrlAuthorizationModule.CheckUrlAccessForPrincipal(virtualPath,
      RC.HttpContext.User,
      RC.HttpContext.Request.HttpMethod))
    {
      if (virtualPath != null)
      {
        return (Page)BuildManager.CreateInstanceFromVirtualPath(virtualPath, typeof(Page));
      }
    }
    else
    {
      throw new SecurityException();
    }

    return null;
  }
}

For each routed request handled by MEOSimpleRouteHandler we now explicitly check if the requested page is authorized for access by the current user and throw a security exception if the user is not authorised to access the page. This works for Forms and Windows authentication and supports Roles.

Technorati Tags: asp.net,routing,security,authorization