HTTP Message Handler in Web API: Implement Authentication Using Custom Message Handler

This is the “HTTP Message Handler in Web API” article series. In our previous articles we have learned various concepts of custom HTTP Message Handlers. You can read them here.

In this article we will implement an authentication process using a custom Message Handler. We all know that an authentication is the process of the user proving her credentials before accessing the system. When we log onto our computer, we provide our credentials to let the system know who I am. And whether I am able to prove myself that I am indeed who I say I am.

In a service based application authentication plays a vital role in terms of security implementation. One service based application might run anywhere in any hardware box and it don’t know about its client. There is a great chance of unauthorized access if anyone knows the service URL (or RESTFul URL in API).

To prevent the unauthorized access we can implement our own authentication process.

Though there are many ways to perform the authentication process, in this article we will implement a token verification system to authenticate users.
The step of operation is as in the following.

The client will send an authentication token in the header of a HTTP request and in the custom Message Handler we will check whether the user has sent the proper authentication token or not. If the authentication token is OK then we will allow the request to reach the target controller otherwise we will return our own response message.

So, let’s implement it practically.

Step 1: Create client application that will send the GET request to the API

Here is a sample implementation of an ajax() client that will perform the GET request to the Values controller. The important part of this example is the beforeSend() callback function where we are inserting a token value to the HTTP request.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="TestWEB_API.WebForm1" %>

<head id="Head1" runat="server">

<script type="text/javascript" src="Scripts/jquery-1.7.1.min.js"></script>

<script>

    $(document).ready(function () {

        $.ajax({

            url: 'http://localhost:11129/api/values',

            type: 'GET',

            dataType: 'json',

            success: function (data, textStatus, xhr) {

                console.log(JSON.stringify(data));

            },

            error: function (xhr, textStatus, errorThrown) {

                console.log(xhr);

            },

            beforeSend: function (xhr) {

                xhr.setRequestHeader("Authorization", "Mytoken");

            }

        });

    });

</script>

</head>

<body>

</body>

</html>

For the sake of simplicity we did not encode the token value, but in a real scenario we should use some encoding mechanism before sending a token value through a HTTP request to protect us from packet sniffing or some other type of attack.

Fine, we have done our client-side implementation. Now we will move to the Web API part where we will configure a custom Message Handler to check the HTTP header.

Step 2: Implement custom Message Handler

It's now time to implement the custom Message Handler, to check the authentication token from the HTTP header. Have a look at the following code. This is the complete code of my Global.asax page.

using System;

using System.Collections.Generic;

using System.Diagnostics;

using System.Linq;

using System.Net;

using System.Net.Http;

using System.Threading;

using System.Threading.Tasks;

using System.Web;

using System.Web.Http;

using System.Web.Http.Filters;

using System.Web.Http.WebHost;

using System.Web.Mvc;

using System.Web.Optimization;

using System.Web.Routing;

using System.Web.SessionState;

 

namespace TestWEB_API

{  

    public class WebApiApplication : System.Web.HttpApplication

    {

        protected void Application_Start()

        { 

            WebApiConfig.Register(GlobalConfiguration.Configuration);

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

            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

            RouteConfig.RegisterRoutes(RouteTable.Routes);

            BundleConfig.RegisterBundles(BundleTable.Bundles);

        }

    } 

    public class MessageHandler1 : DelegatingHandler

    {      

           protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

           {

               string token;

               try

               {

                   token = request.Headers.GetValues("Authorization").FirstOrDefault();

                   if (token != "Mytoken")

                   {

                       //Code for authenticate user. We got authentication ticket

 

                           return await Task.Factory.StartNew(() =>

                           {

                               return new HttpResponseMessage(HttpStatusCode.BadRequest)

                               {

                                   Content = new StringContent("sorry !! you are not authentic user")

                               };

                           });

                   }

                   else

                   {

                       return await base.SendAsync(request, cancellationToken);

                   } 

               }

               catch (System.InvalidOperationException)

               {

                   return null;

               }

           }

    }

}

We are trying to get the value from the HTTP header with the key “ Authorization”.

If the value of the “Authorization” key is “Mytoken” then we will consider the request as a valid request, otherwise it’s a forbidden request.

Now, again for the sake of simplicity we did not implement any validation logic with the DB or any persistent storage media. We are just checking with a string constant. In a real application most probably you need to write logic to verify with the database.

Step 3: Implement Get() action with controller

We will now implement one Get() action that we will call using the ajax() function. Here is sample code for that.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net;

using System.Net.Http;

using System.Web;

using TestWEB_API.Models;

using System.Web.SessionState;

using System.Web.Http;

using System.Web.Mvc;

 

namespace TestWEB_API.Controllers

{

    public class ValuesController : ApiController

    {

        //api/Get

        public string[] Get()

        {

            return new string[] {"Sourav","Kayal" };

        }

    }

}

And we are getting the value from the Get() action within the ajax() success callback.

Get Action with Controller

Cheers! We got data from the API after successful verification. We will now change the value of the authentication token and again we will perform the same GET request to the same controller. Have a look at the beforeSend() method where we have changed the value of the Authorization key.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="TestWEB_API.WebForm1" %>

<head id="Head1" runat="server">

<script type="text/javascript" src="Scripts/jquery-1.7.1.min.js"></script>

<script>

    $(document).ready(function () {

        $.ajax({

            url: 'http://localhost:11129/api/values',

            type: 'GET',

            dataType: 'json',

            success: function (data, textStatus, xhr) {

                console.log(JSON.stringify(data));

            },

            error: function (xhr, textStatus, errorThrown) {

                console.log(xhr);

            },

            beforeSend: function (xhr) {

                xhr.setRequestHeader("Authorization", "Mytoken123");

            }

        });

    });

</script>

</head>

<body>

</body>

</html>

And we are getting this XHR response. We are getting our custom HTTP response (bad request) or instead of the Bad request we could send unauthorized access, or anything.

XHR response

Conclusion

In this article we have learned to implement an “Authentication” process using the Web API. I hope you have learned it. In the future in a few more articles we will learn a few more interesting concepts of this.