Basic Authentication with ASP.NET Web API

Back in 2000, in one of our projects, we used XML over HTTP. We had our own protocol enforced through XSDs. At that time, I did not know that this will be called POX over HTTP. Anyways, web services – SOAP based or not, have been around for a while. ASMX once was the favorite and is now a legacy technology with WCF being the foundation of choice for any services development in Microsoft stack. WCF is cool but has SOAP affinity. Soap is not bad and I use it every day but I do hate the soap scum. RESTful services are better and WCF does support such services to be created.

For anyone who has spent some time on ASP.NET MVC, it is very natural to use action methods returning JsonResult to be consumed by the client. To do Ajax stuff, I can use WCF in the server side but if the application is already leveraging ASP.NET MVC, it is convenient to use an action method for this purpose. But such arrangement gets RPC-ish with action method, mostly a verb, being in the URL.

Enters ASP.NET Web API – a ‘framework that makes it easy to build HTTP services that reach a broad range of clients, including browsers and mobile devices. ASP.NET Web API is an ideal platform for building RESTful applications on the .NET Framework’. Cool! Looks like I have a great framework to build my services. Now, first question that comes to my mind is how to secure them. Don’t want to use anything related to SOAP.

Since Web API is 100% HTTP, why not use something supported by HTTP like the Basic Authentication.

Basic Authentication


It is simple – client asks for the resource. Server answers back with a 401 and WWW-Authenticate : Basic. Client now sends an authorization header Authorization: Basic YmFkcmk6U2VjcmV0U2F1Y2U= with credentials. Header value is just Base64 encoded and not encrypted in anyway. Base64(user id : password), to be exact. If someone is knowledgeable enough to sniff the HTTP traffic and take a peek at the header value, you can assume this person will know how to extract the credentials off the header. So, this is no real security and HTTPS is a must. To implement basic authentication, ASP.NET Web API has extensibility points in the form of handlers – class inheriting DelegatingHandler such as the one below.

protected override Task<HttpResponseMessage> SendAsync(
                                    HttpRequestMessage request,
                                    CancellationToken cancellationToken)
{
    try
    {
        var headers = request.Headers;
        if (headers.Authorization != null)
        {
            // headers.Authorization.Scheme has to be BASIC
            // headers.Authorization.Parameter is Base64
            // encoded user id : password
            // Do your stuff here based on user id and password and
            // create a principal and set it to
            // request.Properties[HttpPropertyKeys.UserPrincipalKey]
        }

        return base.SendAsync(request, cancellationToken)
                     .ContinueWith((task) =>
        {
            var response = task.Result;

            if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                 response.Headers.WwwAuthenticate.Add(
                               new AuthenticationHeaderValue("Basic"));
            }

            return response;
        });
    }
    catch (Exception)
    {
        return Task<HttpResponseMessage>.Factory.StartNew(() =>
        {
            var response = new HttpResponseMessage
                               (HttpStatusCode.Unauthorized);
            response.Headers.WwwAuthenticate.Add(
                 new AuthenticationHeaderValue("Basic"));

            return response;
        });
   }
}

Handler has to be registered in Application_Start() in Global.asax.cs like this.


GlobalConfiguration.Configuration.MessageHandlers
     .Add(new AuthenticationHandler());

The handler above is forgiving. Only when an authorization is present, it does it’s stuff. Of course, it can be changed to check for all requests and send back a 401. Finally, action method has to be decorated with [Authorize] attribute. It is really messy to put this in all the action methods – people tend to forget and all that. Luckily, it can be done globally, again in Global.asax.cs.

GlobalConfiguration.Configuration.Filters
     .Add(new System.Web.Http.AuthorizeAttribute());
Advertisements

2 thoughts on “Basic Authentication with ASP.NET Web API

  1. Yes, Allen. You are right. The message handler is named AuthenticationHandler but I showed only the SendAsync method of that class in the code listing.

  2. I assume the name of the class containing the override of ‘SendAsync’ is named ‘AuthenticationHandler’ correct? You refer to ‘AuthenticationHandler’ registration in Global.asax, but never show it’s implmentation.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s