Sunday, July 21, 2013

Simple.Web - Extending Handler Behaviors

I have continued working with Simple.Web and recently integrated a project with Azure Active Directory. To my surprise it was actually pretty easy to provision AD on Azure and then use Windows Identity Foundation (WIF) to integrate it into the project. Since I can run Simple.Web with ASP.NET, it all "Just Works." There are some annoying things about Azure AD (that go above an beyond the annoyances of AD itself) but I'll save that for another post.

At any rate, the reason for this post is to talk about extending the behaviors that come packaged in Simple.Web. When I first got Azure AD integrated, it was easy to slap on an IRequireAuthentication behavior on my handler, run the app, and then get redirected to the Azure AD login page. My project, though, is a multi-tenant app and I need the tenant id as well and the user's id. I could easily create a new behavior and slap it onto my handlers without much thought but I wanted to avoid the situation where there are a million-and-one interfaces on each handler since they're all required. So, I tried extending the IRequireAuthorization behavior and, to my surprise, it worked like a charm.

So, the first thing to do was create the interface:

using System;
using Simple.Web.Behaviors;

public interface IRequireTenant : IRequireAuthentication
{
    Guid TenantId { set; }
}

The next step was to create the "implementation":

using System;
using System.Security.Claims;
using Simple.Web.Http;

public static class SetTenant
{
    public static bool Impl(IRequireTenant handler, IContext context)
    {
        var cp = ClaimsPrincipal.Current;
        Guid tenantId;
        if (Guid.TryParse("http://schemas.microsoft.com/identity/claims/tenantid").Value, out tenantId))
        {
            handler.TenantId = tenantId;
            return true;
        }

        return false;
    }
}

And then go back and decorate the interface with the implementation:

[RequestBehavior(typeof(SetTenant))]
public interface IRequireTenant : IRequireAuthentication { ... }

Simple.Web still treats the handler as though it has the IRequireAuthentication behavior (it still triggers the AuthenticationProvider and redirects if needed) and I don't need to have a bunch of interfaces all over my handlers.

No comments:

Post a Comment