Daniel Fisher (lennybacon.com)

SOA, DATA & THE WEB

UrlAuthorization with ASP.NET Routing

What is life without security. In the last posts I told you how to do URLRewriting with the ASP.NET 3.5 RoutingEngine and how to pass query strings to the destination Web Form. In this post I'll add some authorization code to let ASP.NET Authentication mechanisms play well.

The first step is to figure out which authentication mechanism has taken place in the local configuration file. For the case of forms based authentication it would be nice to redirect to the configured login Web Form, for all other authentication mechanisms we can only throw a security exception and set a HTTP status code.

I only wanted this operation to be executed once and therefore I implemented as static and thread safe property with a backing field and a lock object:

private static string s_authenticationType;
private static object s_authenticationTypeLock = new object();
private static string AuthenticationType
{
    get
    {
        if (string.IsNullOrEmpty(s_authenticationType))
        {
            lock (s_authenticationTypeLock)
            {
                if (string.IsNullOrEmpty(s_authenticationType))
                {
                    var authenticationSectionObject =
                        WebConfigurationManager.GetSection(
                        "system.web/authentication");

                    var authenticationSection =
                        authenticationSectionObject
                            as AuthenticationSection;

                    if (authenticationSection != null)
                    {
                        s_authenticationType =
                            authenticationSection.Mode.ToString();
                    }
                }
            }
        }
        return s_authenticationType;
    }
}

 

Now its time to check the authorization on the target Web Form:

if (httpContext != null &&
    !UrlAuthorizationModule.CheckUrlAccessForPrincipal(
        VirtualPath,
        httpContext.User,
        httpContext.Request.HttpMethod))
{
    if (AuthenticationType.
        Equals("forms", StringComparison.OrdinalIgnoreCase))
    {
        VirtualPath = FormsAuthentication.LoginUrl;
        queryString =
            new StringBuilder(
                string.Concat(
                    "?ReturnUrl=",
                    requestContext.HttpContext.Server.UrlEncode(
                        requestContext.HttpContext.Request.RawUrl
                        )));
    }
    else
    {
        throw (new SecurityException());
    }
}

Next I will add a login Web Form to the site and drop a LoginControl to the form:

image

And add some code behind:

using System;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class login : Page
{
    protected void OnLoggingIn(object sender, LoginCancelEventArgs e)
    {
        //TODO: add some auth logic or use membership...
        FormsAuthentication.RedirectFromLoginPage(
            "lennybacon", 
            false);
    }
}

Authorization requires an authorization and therefore I enable ASP.NET forms based authentication that also is compatible to ASP.NET Membership in the configuration file:

<configuration>
  <system.web>
    <authentication mode="Forms"/>
...

 

I can configure the authorization settings for the destination Web Forms are also in the web.config file by adding location sections:

<configuration>
  ...
  <location path="Default2.aspx">
    <system.web>
      <authorization>
        <deny users="?"/>
      </authorization>
    </system.web>
  </location>
...

 

Running the web site and clicking the link to the route (/other) that targets the Default2.aspx results in showing up the login.aspx.

image

Notice that the address bar has not changed - the usual roundtrip for redirecting to the loginURL is also "rewritten" inside of ASP.NET.

 

This way the security is easily plugged into the RoutingHandler class - Cool stuff! 

Comments

Hi, I have similar code in my site built from samples on other sites - the only real difference is that I don't check the config file to get the authentication type since it's always going to be Forms authentication. Calling UrlAuthorizationModule.CheckUrlAccessForPrincipal(...) causes an error because the httpContext.User has no value. Any idea where I'm going wrong or how I can work around thi

Write a comment