piotrwalat.net

Basic HTTP authentication in ASP.NET Web API using membership provider

17 comments

In this blog post I am going to show how to provide Basic HTTP authentication in a Web API project by extending framework’s AuthotrizeAttribute.

ASP.NET Web API is a great tool to create lightweight, HTTP-based APIs for your internet and mobile applications. In most scenarios you will need to provide some kind of authentication and authorization mechanism to restrict and isolate resources exposed by your services. Security in ASP.NET Web API is deferred to the hosting infrastructure. When running within IIS, authorization mechanism runs on top of an existing ASP.NET security system, meaning you can leverage existing features like … good ‘ol membership and role providers.

HTTP authentication

Out of the box ASP.NET provides two types of authentication that can be easily used within Web API:

  • forms authentication
  • windows authentication

For obvious reasons windows authentication is not an option with Internet exposed services. Forms authentication on the other hand is a mechanism that works well in interactive applications (eg. a website), but because of its cookie-based nature is not entirely REST friendly (as we need to be aware of the state) and requires clients to manage cookies on their side. Its not an issue when services are invoked from the browser (eg. using jQuery), as it will remember cookies for us, but may introduce another layer of complexity when consumed by mobile platforms.

HTTP authentication on the other hand is part of the standard protocol and can be easily handled by most popular client and mobile platforms.

Basic HTTP authentication sends credentials in plaintext (unencrypted) which means you must use secure transport layer (SSL) to provide encryption.

Creating ASP.NET Web API project

Let’s start off by creating a new ASP.NET MVC 4 project and selecting Web API template for it. You may delete unnecessary Views, .css and .js files as we care only about bare minimum needed to host Web API services (Global.asax, Web.config and a controller).

Please note that currently (May 2012) Web API is still in a pre-release stage, which means breaking changes may be included in future releases. While building this example I have been using the latest source code available at the time of writing. To have the latest version you can use either git to clone the repository available at https://git01.codeplex.com/aspnetwebstack.git or use NuGet and nightly build packages provided (see this blog for more information).

Let’s add a very simple model for the sake of example (it’s not that important)

System.Web.Http.Authorize filter

Next, create a simple controller. Any method would do, but GET will be the easiest to test. Web API ships with System.Web.Http.Authorize filter attribute that can be used to restrict access to certain actions or controllers (note that this is not System.Web.Mvc.AuthorizeAttribute from ASP.NET MVC, but its equivalent).

Thats all you need to do to prevent anonymous users from reading your books! Because by default WebAPI project is configured to use forms authentication when you try to get the resource you will be redirected to a non-existent login url.

ASP.NET will intercept unauthorized response (from Authorize attribute) and change it to 302 redirection response. To disable this behavior turn off forms authentication in your web.config file.

;

Custom authorization filter

You may be tempted to implement HTTP Authentication in your controller. This is usually a bad idea, partially because of potential caching issues and partially because having authorization logic in controllers is a bad design. Jon Galloway explained it here for ASP.NET MVC. Deriving from Authorize filter is a potential way to customize the way ASP.NET MVC integrates with the underlying ASP.NET security system.

So let’s try this approach and derive from AuthorizationAttribute and create a filter that will handle HTTP basic authentication.

The most important part of the filter is its OnAuthorization(HttpActionContext actionContext) method that sets HTTP headers and HTTP response in case of unauthorized requests. Please note that we want developers be able to selectively disable authentication using AllowAnonymousAttribute – thats the logic handled by AuthorizationDisabled method.

The class itself is abstract and its concrete implementations should do actual checks against user datastore. Alternatively we could have used dependency injection and some kind of interface to abstract user retrieval.

Using membership and role provider

To add support for membership and role providers from our web.config we need to provide a simple BasicHttpAuthorizeAttribute implementation.

Of course you need to configure your providers in .config file as well as provide database to store your users.

Now you can decorate actions and controllers with the newly created attribute to use MembershipProvider-backed HTTP authentication with your service.

So is this approach ideal? Well, obviously not. Its better than having all authorization logic in controllers, but still its not perfect. We have coupled our controller with a concrete authentication method. Depending on your application needs it may or may not pose a problem to maintainability. In many small mobile apps that’s probably not something to be too worried about. The solution to this flaw would be either to use dependency injection (and for example fluent security configuration) instead of abstract classes or to use custom ASP.NET HTTP module. But that’s material for another blog post :)

Anyway HTTP Authentication + Web API seems like a very good combination to get a lightweight, standard compliant and secure service layer for mobile apps.

Written by Piotr Walat

May 17th, 2012 at 11:09 pm

  • David Gray

    Interesting approach – FYI I shared on the LIDNUG LinkedIn group http://lnkd.in/Tst4rS

    • Piotr Walat

      Thanks David, much appreciated!

  • Zula

    would be very good if you copy all the code for an example … copy parts a waste of time

  • Ignacio Fuentes

    Hey Piotr,
    Not trying to diss your code but to me it really is kind of mind boggling how something as simple as http basic can get so complicated.
    I was just looking at how easy it is to do the same task on a ruby on rails based wep api and I have to admit it kind of makes me jealous.

    http://railscasts.com/episodes/352-securing-an-api

    what do you think?
    Can we make something even close to the simplicity of that in asp.net web api?

    • http://www.piotrwalat.net/ Piotr Walat

      Hi Ignacio,
      Please take a look at http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-message-handlers/ it’s a cleaner approach and one I would recommend.
      Edit: nvm, I see you already did see it and even commented there :) Thanks!

  • wormcz

    Works perfectly. Thank you very much!

  • Pingback: Basic HTTP authentication in ASP.NET Web API using message handlers at piotrwalat.net

  • Andreas Louk

    it looks promising.. but i can’t get it to work though.. can i use this to implement login authentication from my mobile app? i’m developing android app to log in using webAPI.. can you please give me a complete direction to do this… or if i may have the complete code…    acl_andre@yahoo.com

  • http://www.facebook.com/profile.php?id=100002562434494 Joshua Barrett

    Total noob at mvc 4 web api, and still brushing up on C#… so please excuse my ignorance…  Where would one put the BasicHttpAuthorizeAttribute class? in the controller?

    • http://www.piotrwalat.net/ Piotr Walat

      It’s an attribute – you would decorate a controller/action method with it, like this

      [BasicHttpAuthorizeAttribute]
      public class MyAwesomeController : ApiController{ }Hope this helps.PS. Please take a look at http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-message-handlers/ it’s a better approach to this problem.

      • http://www.facebook.com/profile.php?id=100002562434494 Joshua Barrett

        Will do! I really appreciate your response

      • http://www.facebook.com/profile.php?id=100002562434494 Joshua Barrett

        Piotr, This(the link you provided) works locally but when I deploy to my webserver it just keeps poping up a login box.  using fiddler it never gets through

  • Ron Wang

    Hi Piotr,
    Very nice post. Can you provide some info how to integrate with simpleMembership provided by MVC4 by default?
    Thanks 

  • tarini.venugopal

    Hey Piotr,
    Can we use Windows Authentication with ASP.Net membership provider for asp.net web api ?? How one api will authenticate with other api which is also windows identity enabled ??

  • Pingback: benpowell.org

  • Olivier Alessandri

    Hi Piotr,

    I do not understand how do you set the parameter (login / password) in the query? Should pass as parameter in url? to get in post? Parameters are it hashed in the header? Would you have an example of C # code?

    thank you

    • http://www.piotrwalat.net/ Piotr Walat

      You send username and password pair encoded as base64 string in Authorization header like this:

      Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

      In practice all major programming platforms provide some kind of support for basic http authentication. For example using HttpClient in .NET you could do something like:

      var credentials = "username:password";
      var encoded = Convert.ToBase64String(Encoding
      .ASCII.GetBytes(credentials));
      client.DefaultRequestHeaders.Authorization
      = new AuthenticationHeaderValue("Basic,", encoded);