Inject IPrincipal in ASP.NET Web API Controller

In ASP.NET MVC the current IPrincipal can be automatically made available to action methods by implementing the System.Web.Mvc.IModelBinder interface and returning the current authenticated user from HttpContext.User. We can accomplish the same in Web API using the HttpParameterBinding class.

namespace App.Web.Http.Helpers
{
    public class PrincipalParameterBinding : HttpParameterBinding
    {
        public PrincipalParameterBinding(HttpParameterDescriptor des)
            : base(des) { }

        public override Task ExecuteBindingAsync(
            ModelMetadataProvider metadataProvider,
            HttpActionContext actionContext, 
            CancellationToken cancellationToken)
        {
            SetValue(actionContext, Thread.CurrentPrincipal);

            return Task.FromResult<object>(null);
        }
    }
}

Create a [IPrincipalParameterBinding] attribute.

namespace App.Web.Http.Helpers  
{
    public class IPrincipalParameterAttribute : ParameterBindingAttribute
    {
        public override HttpParameterBinding GetBinding(
            HttpParameterDescriptor desc)
        {
            if (desc.ParameterType == typeof(IPrincipal))
            {
                return new PrincipalParameterBinding(desc);
            }

            return parameter.BindAsError("Expected type IPrincipal");
        }
    }
}

Apply the [IPrincipalParameter] attribute on the method parameter.

[RoutePrefix("api")]
public class MainController : ApiController  
{
    [Route("whoami")]
    public string GetPrincipal(
        [IPrincipalParameter]
        IPrincipal principal) { ... }
    {
        return principal.Identity.Name;
    }
}

Alternatively, we can add it globally during application startup.

using App.Web.Http.Helpers;

namespace App.Web  
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // add the rule to the collection
            config.ParameterBindingRules
                  .Add(typeof(IPrincipal), 
                       des => new PrincipalParameterBinding(des));
        }
    }
}

Inject the IPrincipal parameter:

[RoutePrefix("api")]
public class MainController : ApiController  
{
    [Route("whoami")]
    public string GetPrincipal(IPrincipal principal)
    {
        return principal.Identity.Name;
    }
}