asp.net-web-apithinktecture-ident-model

Role-based authorization in ASP.NET Web API - how to set roles on the principal?


I am using recipe 10-3 in the newly released book ASP.NET Web Api 2 Recipes to support basic authentication in my Web API. This recipe utilizes a 3rd party library from Thinktecture. As seen from the below code, I am authentication the user against my own account service.

using Thinktecture.IdentityModel.WebApi.Authentication.Handler;

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        ...            

        var authenticationConfiguration = new AuthenticationConfiguration();
        var accountService = ServiceLocator.Get<AccountService>();
        authenticationConfiguration.AddBasicAuthentication((userName, password) => accountService.Authenticate(userName, password));
        config.MessageHandlers.Add(new AuthenticationHandler(authenticationConfiguration));

        ...
   }
}

Now I want to make role-based authorization in my controllers using the Authorize attribute:

[Authorize(Roles="administrator")]
public IHttpActionResult Get()
{
    ...
}

My account service obviously knows about the users and their assigned roles, but this information is not available to the Authorize attibute (the roles are not set on the principal).

How do I accomplish this? Can the Thinktecture authentication handler be configured to set the roles on the principal? Or should I make my own custom Authorize attribute (deriving from the Authorize attribute)? And if so, should I override the OnAuthorization method to create and set the principal using my account service? Or maybe override the IsAuthorized method directly? Or maybe something else...


Solution

  • I found out that the AddBasicAutentication method actually has an overload that takes a delegate for providing the roles. This is exactly what I was looking for. So now the call to AddBasicAuthentication looks like this, and everything works like a charm:

    authenticationConfiguration.AddBasicAuthentication((userName, password) => accountService.Authenticate(userName, password), (username) => accountService.GetRoles(username));