Saturday, 13 April 2013

ASP.Net Web Api Header authorisation and Sencha Touch 2 Request

Recently on the Questo Project that I have been working I needed to create a quick way of locking certain features from the API where only authorised users should be able to use it.

ASP.Net WebApi Code

AuthorizationFilterAttribute

The easiest way to protect your code is by adding a filter attribute to your controller or method.
Below is the code that checks the request's headers and validates the api code from it.

If invalid, returns an Unauthorized response to the client.

Important: Note the using namespaces! It is importing the WebApi namespaces rather than the ASP.NET MVC.
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http.Filters;

namespace QuestoApi.Filters
{
    public class WebApiKeyAuthorisationAttribute 
                    : AuthorizationFilterAttribute
    {
        private const string HeaderApikeyName = "ApiKey"; //header name

        public override void OnAuthorization(
            System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            base.OnAuthorization(actionContext);
            
            //AJAX frameworks usually send a OPTIONS, below allows the 
            //options to run as usual.
            if (actionContext.Request.Method == HttpMethod.Options) return;

            string key = null;
            if (actionContext.Request.Headers.Contains(HeaderApikeyName))
            {
                key = actionContext.Request
                                   .Headers
                                   .GetValues(HeaderApikeyName)
                                   .FirstOrDefault();
            }

            if (ValidateApiKey(key))
            {
                //If it is valid, no need to do anything
                //But alternatively, you can set the HttpContext User 
                //to allow your app identify the user who is calling the API
                
                //HttpContext.Current.User = GeneratePrincipal();
            }
            else
            {
                //Otherwise, return a response now as an Unauthorized
                actionContext.Response = actionContext
                                          .Request
                                          .CreateResponse(HttpStatusCode.Unauthorized);
            }
        }

        private bool ValidateApiKey(string key)
        {
            //Write here your key validation
            return key == "valid-key";
        }
    }
}

Using on the controller

You can either place the attribute at the class level:
    [WebApiKeyAuthorisation]
    public class RegisterQuestController : ApiController
Or at method level:
        [WebApiKeyAuthorisation]
        public HttpResponseMessage PostUserQuest(RegisterQuestRequest p)
 
When placing the attribute, that method or controller will be protected requiring the client to always include the api key into the header of the request.
 
Once the ApiKey is validated, you can optionally access the user details from the
HttpContext.Current.User = GeneratePrincipal();
 
Note: When placing at class level all methods will use the filter. Fear not, there are ways of allowing anonymous authorization on selected methods - but fear now, you will have to do your own research :) I have seen somewhere.

Adding Header to Sencha Ext Ajax Request

How to use this using Sencha Tounch 2 Ext:

Ext.Ajax.request({
    url: url,
    method: 'POST',
    headers: {
        'Content-Type': 'application/json;charset=utf-8',
        'Accept': 'application/json',
        'QuestoApiKey': 'valid-key'
    },

    params: data, //your data

    failure: failureCallback,
    success: successCallback
});