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;
}
}