Basic Auth with a Web API 2 IAuthenticationFilter

27/02/2014 § 3 Comments

MVC5/Web API 2 introduced a new IAuthenticationFilter (as opposed the the IAuthorizationFilter we needed to dual-purpose in the past), as well as a substantial overhaul of the user model with ASP.NET Identity. Unfortunately, the documentation is abysmal, and all the blog articles focus on the System.Web.Mvc.Filters.IAuthenticationFilter, not the System.Web.Http.Filters.IAuthenticationFilter, which is clearly something entirely different.

We had a project where we needed to support a Basic-over-SSL authentication scheme on the ApiControllers for a mobile client, as well as Forms auth for the MVC controllers running the admin interface. We were keen to leverage the new Identity model, mostly as it appears to be a much more coherent design than the legacy hodgepodge we’d used previously. This required a fair bit of decompilation and digging, but I eventually came up with something that worked.

Below is an excerpt of the relevant parts of our BasicAuthFilter class – it authenticates against a UserManager<T> (which could be the default EF version) and creates a (role-less) ClaimsPrincipal if successful.

public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
    var authHeader = context.Request.Headers.Authorization;
    if (authHeader == null || authHeader.Scheme != "Basic")
        context.ErrorResult = Unauthorized(context.Request);
    else
    {
        string[] credentials = ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(authHeader.Parameter)).Split(':');

        if (credentials.Length == 2)
        {
            using (var userManager = CreateUserManager())
            {
                var user = await userManager.FindAsync(credentials[0], credentials[1]);
                if (user != null)
                {
                    var identity = await userManager.CreateIdentityAsync(user, "BasicAuth");
                    context.Principal = new ClaimsPrincipal(new ClaimsIdentity[] { identity });
                }
                else
                    context.ErrorResult = Unauthorized(context.Request);
            }
        }
        else
            context.ErrorResult = Unauthorized(context.Request);
    }
}

public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
{
    context.Result = new AddBasicChallengeResult(context.Result, realm);
    return Task.FromResult(0);
}

private class AddBasicChallengeResult : IHttpActionResult
{
    private IHttpActionResult innerResult;
    private string realm;

    public AddBasicChallengeResult(IHttpActionResult innerResult, string realm)
    {
        this.innerResult = innerResult;
        this.realm = realm;
    }

    public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = await innerResult.ExecuteAsync(cancellationToken);
        if (response.StatusCode == HttpStatusCode.Unauthorized)
            response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue("Basic", String.Format("realm=\"{0}\"", realm)));
        return response;
    }
} 

Note that you’ll need to use config.SuppressDefaultHostAuthentication() in your WebApiConfig in order to prevent redirection from unauthorised API calls.

Book Review: Getting Started with LevelDB

31/01/2014 § 1 Comment

Getting Started with LevelDB

I was asked to review the new LevelDB book from Packt (disclaimer: I know the author and was provided a free electronic copy). I’ve done a reasonable amount of experimental hacking using LevelDB on iOS in the past,so I was keen to see whether there was much I’d learn from a ‘Getting Started’ book.

Firstly, a bit about my background in this area. Thanks to my abiding hatred of all things Core Data (remind me to do a blog post on that later), I’d looked into LevelDB a little while ago as a possible alternative iOS persistence technology. I’ve used NoSQL (document) databases on web projects in the past, and I was looking for something that gives the performance, simplicity and syncability of something like CouchDB or RavenDB on iOS (before you comment, yes, I know about TouchDB and CouchBase Mobile). I found LevelDB to be a little too low-level to offer a complete persistence solution out of the box, and partially managed to avoid the temptation to go off and build one (another blog post). I knew Andy had a background in ISAM and embedded storage engines, not to mention that horrid C++ language, so I was hopeful he’d have some better approaches to real-work usage.

I also should mention there was a mild controversy over the book when it was released – the title implies generic LevelDB content, whereas the book focuses on practical implementation in OS X and iOS applications, which some people felt was misleading. I didn’t have a problem with it, but then I’m only really interested in using it in OS X & iOS applications.

The ‘building and installing’ chapters are quite detailed, and explicitly show things going wrong, provide an explanation why, and show how to rectify it. I found them a little bit tedious, but people inexperienced with building open-source C/C++ projects would probably need the extra hand-holding (to be honest, I ignored the makefile & built LevelDB in Xcode – kudos to the developers for not making the build too exotic).

Andy then goes on to examine the C++ API and explain the query semantics and some of the core idioms and public data structures. This lays important conceptual foundations, but given I was already familiar with these I skimmed over most of it. It’s worth noting the code in these chapters is all defiantly C++ (e.g. cout rather than NSLog etc) – I can understand why this was done, given the disappointing and inconsistent state of Objective-C API options (more on that in a moment), but it doesn’t make it any less jarring.

Finally we hit the Objective-C code and some of the OS X/iOS samples. I had a bit of a chuckle at the line:

Some people also have a strong aversion to C++ and will avoid anything that lacks an Objective-C interface.

(I suspect he’s probably talking about me). Complicating this task is the fact there’s no official or standard Objective-C API for LevelDB, so the book spends a bit of time covering the three most popular open source wrapper interfaces, and duplicates some of the sample code across the three. Eventually Andy settles on a customised version of APLevelDB for the remainder of the book (though I’m not sold on exposing the raw C++ DB reference), however ideally we’d instead have available a popular, stable, complete, well-maintained, idiomatic Cocoa LevelDB wrapper. This could have made the book much simpler and better, and allowed it to spend more time and energy discussing other topics. Hopefully someone who’s not me will write this someday.

Next we receive a walkthrough implementing a basic sample app – the book describes an OS X application, but it’s worth noting all the downloadable code samples include the iOS equivalent. There are also descriptions of some debugging tools, including dump, lev, and implementing a REPL on an iOS device via an embedded web server (quite a clever trick, though I’m not sure if I’ll ever use it). The sample app is then extended with more advanced functionality, and this is where (for me) things really started to get interesting. This included secondary indexes, key design considerations, custom comparators, record-splitting, and ‘schema support’ extensions to assist in maintaining keys. The last was quite a nifty idea – I can see the potential for a declarative (e.g. json file in the app bundle) index definition mechanism. Less code is always better™.

Chapter 9 was titled “A Document Database”, and I hoped it was something closer to what I’ve used in CouchDB. It wasn’t really – the sample was more geared towards a metadata database of external files. However, it does include a basic text indexing implementation, which is an area I’ve battled with before, so it’s given me enough to take this idea further. The links to test indexing algorithms and open source implementations are also invaluable – additional resources are extensively referenced throughout the book; it’s one of the things that’s been done very well.

Chapter 10, “Tuning and Key Policies” is gold, and probably worth the sticker price of the book on its own if you’re serious about implementing a LevelDB solution. It starts out describing LevelDB under the covers – memtables, SSTs, the eponymous levels, snapshots and Bloom filters. The various performance settings are discussed and recommendations made, then Andy gets into a discussion of how to structure data and keys to optimise performance, much of which revolves around understanding when & how often your data is read and updated. He also discusses some optimisations made by Basho in the Riak codebase.

Lastly, the appendix covers using LevelDB from three scripting languages (Ruby, Python & JavaScript (node)), which was worthy of inclusion given I’ve already come across the need to script data in & out of a database.

In summary, I think the book would be invaluable to anyone looking at using LevelDB from Objective-C, and most of it would still be very useful to developers on other platforms. It’s certainly given me a lot to mull over, and rekindled some of my excitement about LevelDB on mobile devices.

Build Server Traffic Lights

16/10/2013 § Leave a comment

Traffic Light

I’ve wanted real build server traffic lights since I first implemented a Continuous Integration server in the mid 2000s. In those days, the trendy thing to do was to hook up red & green lava lamps to your build server, but CCTray’s red/green/yellow status indicators always seemed better suited to traffic lights. However, it was something that always got put in the ‘someday’ pile. More recently, I’d become interested in hardware automation platforms like Arduino, and it seemed like an ideal first project, so I dusted off the concept.

Obtaining the traffic light unit itself was relatively straightforward – in WA, the old style incandescent units are being progressively replaced with LEDs, so the reasoning was there’d be some that are superfluous to requirements. A few phone calls later, I managed to track down the contractor handling the replacement and do a beverage-related deal for a second-hand traffic light. The hardest part was actually explaining what I intended to do with it!

These traffic light units don’t contain any switching logic or complex electronics at all – they have a 240VAC feed for each light, with industrial grade internal transformers stepping down to 10V and driving 20W high-pressure bulbs. I’d seen reports that the standard bulbs were too bright for indoor use, but a test run showed it was probably just okay, and it was certainly much simpler to keep the lighting as-is while I got the rest of the hardware working.

Traffic Light 3The intention was to run the lights as a networked device (rather than a USB one, requiring an active host computer), as this would enable more flexibility in installation. I ordered an Arduino Ethernet and relay shield from Little Bird Electronics, and set about coding the controller software.

Traffic Light UI

The code is available online here – it’s adapted from a similar project by Dirk Engels. The Arduino runs a web server that serves a page displaying the current status of the light, as well as buttons to control the light and RESTful control URLs to provide build server integration. My main changes to the design were:

  • Integration of a DHCP library, to remove the hard-coded IP address and make it possible to move the light between networks without reprogramming.
  • Bonjour support, to advertise the light at ‘traffic-light.local’ and remove any requirement for DNS entries/DHCP reservations on the network.
  • A failover mode that flashes amber if the light has not heard from the build server in over 5 minutes. This mimics real world behaviour and seemed more appropriate than turning off or displaying the last known state indefinitely.

Traffic Light 2

Wiring in the controller was pretty simple – the 240V mains feed powers the 9V DC power supply for the Arduino, as well as the 10V transformers for the lights via the relay shield. Initially these were switched on the high-voltage side, but the inrush current appeared to play havoc with small switch-mode power supplies (i.e. phone chargers) on the same circuit, so I rewired to switch on the low-voltage side. This also allowed me to remove two of the transformers and freed up some internal space; I ended up being able to neatly mount the controller on one of the unused transformer brackets.

Traffic Light 4Obviously the light needed a pole; I constructed one using galvanised fence post and some sub-par oxy welding. I would have liked to run the wiring down inside the pole, but unfortunately the size of the mains plug was going to make this difficult (given I wanted the light to stay easily removable). A few coats of suitable yellow paint and it was good to go.

After installing the light in the office, we developed a small powershell script to query the build server and update the light. It’s had a significant benefit in putting the build status unavoidably in front of the developers, and the builds have become noticeably more ‘green’ than they have been for some time.

There are a few areas I’d design differently if I did it again:

  • Use a hardware flasher circuit for the failover mode (via the fourth relay) – the software flasher works okay, but there’s a noticeable stutter in the flashes if the controller is doing something else (like responding to a web request). I’m not enough of a hardware whiz to build one of these though.
  • Install bulkhead RJ45 & 3-pin PC power connections on the traffic light housing, so that the cables are detachable – this would permit variable cable lengths and potentially allow routing inside the pole.
  • Use low-wattage bulbs rather than the specialised 20W high pressure bulbs – the traffic light is a bit bright straight-on. Unfortunately the existing bulb holders have a unique bayonet mount and they’d need to be replaced with something else (e.g. automotive BA15S).

EntityPropertyMappingAttribute duplicated between assemblies

09/10/2013 § Leave a comment

I was working on an entity class for an OData endpoint when I ran across the following doozy:

The type ‘System.Data.Services.Common.EntityPropertyMappingAttribute’ exists in both ‘…Microsoft.Data.OData.dll’ and ‘…System.Data.Services.Client.dll’

It looks like Microsoft has duplicated this type (plus a couple of others) between two different assemblies – in this instance I ran across it with the Azure.Storage package.

Thankfully, Jon Skeet to the rescue! To resolve:

  1. Select the System.Data.Services.Client reference and open the properties dialog
  2. Under ‘Aliases’, change ‘global’ to ‘global,SystemDataServicesClient’
  3. Add the following code at the top of the offending entity file:
extern alias SystemDataServicesClient;
using SystemDataServicesClient::System.Data.Services.Common;

You’ll also need to delete your other using System.Data.Services.Common, but at that point you should be compiling again.

Set-ExecutionPolicy is architecture-specific

22/08/2013 § Leave a comment

I was repeatedly getting “execution of scripts is disabled on this system” while attempting to run Invoke-Command on a remote machine, even after running Set-ExecutionPolicy RemoteSigned on that box.

Eventually the penny dropped – I’d been running 32 bit Powershell interactively, whereas Invoke-Command appeared to be running 64 bit Powershell. The Powershell designers, in their infinite wisdom, made the execution policy separate for the 32 & 64 bit versions. I guess that’s not quite as bad as installing Powershell 3.0 under the directory ‘WindowsPowershell\1.0’.

Re-running Set-ExecutionPolicy RemoteSigned in the 64 bit Powershell console solved the issue.

Azure AD Single Sign On with multiple environments (Reply URLs)

17/07/2013 § 1 Comment

As part of an effort to move some internal applications to the cloud (sorry, The Cloud™), I recently went through the process of implementing Azure AD single sign on against our Office365 tenant directory. Working through the excellent MSDN tutorial, I hit the following (where it was describing how to reconfigure Azure AD to deploy your app to production):

Locate the REPLY URL text box, and enter there the address of your target Windows Azure Web Site (for example, https://aadga.windowsazure.net/). That will let Windows Azure AD to return tokens to your Windows Azure Web Site location upon successful authentication (as opposed to the development time location you used earlier in the thread). Once you updated the value, hit SAVE in the command bar at the bottom of the screen.

Wait, what? This appears to imply  Azure AD can’t authenticate an application in more than one environment (eg if you want to run a production & test environment, or, I don’t know, RUN IT LOCALLY) without setting up duplicate Azure applications and making fairly extensive changes to the web.config. Surely there’s a better way?

I noticed that the current version of the Azure management console allows for multiple Reply URL values:
Azure AD Reply URLs

However, just adding another URL didn’t work – the authentication still only redirected to the topmost value.

The key was the \\system.identityModel.services\federationConfiguration\wsFederation@reply attribute in web.config – adding this attribute sent through the reply URL and allowed authentication via the same Azure AD application from multiple environments, with only relatively minor web.config changes.

As the simplest solution, here’s an example Web.Release.config transform – more advanced scenarios could involve scripting xml edits during a build step to automatically configure by environment.

 <system.identityModel.services>
    <federationConfiguration>
      <wsFederation reply="<<your prod url>>" xdt:Transform="SetAttributes" />
    </federationConfiguration>
  </system.identityModel.services>

Testing a SignalR application using WebDriver in IE9

16/04/2013 § Leave a comment

I was having problems testing a SignalR application in IE9 using the Selenium IEServerDriver – the WebDriver instance would block indefinitely after navigating to a page that starts a hub connection.

SignalR Issue 293 seems to imply that the IE WebDriver is not compatible with foreverFrame – it never recognises that the page has finished loading. Changing the hub connection code to:


$.connection.hub.start({ transport: ['longPolling', 'webSockets'] });

fixed the issue and made IE9 testable again via WebDriver.

Follow

Get every new post delivered to your Inbox.