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
});

3 comments:

  1. What is the usage of the ApiKey?

    Someone can steal the api key ,using very easy methods, and do what he want.

    ReplyDelete
    Replies
    1. The demonstration above is a quick way of locking your api if you need to. To make it secure you'd need to implement your own token renewal and stuff like that.

      The code above is not production ready at all, but a simple way of prototyping something with reduced effort at server and client side (i.e. compared to oauth, hawk, etc)

      Delete
  2. Its very informative blog and useful article thank you for sharing with us , keep posting learn
    Dot NET Online Course bangalore

    ReplyDelete