In our asp.net mvc/web api project, we want to customize the authorization using AuthorizeAttribute
. We have noticed that there are two different AuthorizeAttribute
, one in System.Web.MVC
namespace for MVC and the other in System.Net.Http
namespace for web api.
It works in MVC, our code like this:
public class MyPrincipal : IPrincipal
{
//some custom properties
public bool IsValid()
{
//custom authentication logic
}
private IIdentity identity;
public IIdentity Identity
{
get { return this.identity; }
}
public bool IsInRole(string role)
{
return true;
}
}
//override AuthorizeCore
public class MyAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
MyPrincipal user = new MyPrincipal();
if (user.isValid())
{
httpContext.User = user;
}
else
{
httpContext.Response.Redirect("~/Common/NoAuthorize", true);
}
}
}
[MyAuthorizeAttribute]
public class BaseMyController : Controller
{
protected virtual new MyPrincipal User
{
get { return HttpContext.User as MyPrincipal; }
}
}
Then in MVC controller,we can get the user information via MyPrincipal
user property.
However, when we start to use the same way in web api, we found that the web api has no HttpContext
property and in System.Web.Http.AuthorizeAttribute
, the method to be override accepts a HttpActionContext
argument, it also has no HttpContext
property or some where else we can set the MyPrincipal
instance.
I notice that the System.Web.Http.AuthorizeAttribute
summary says
Specifies the authorization filter that verifies the request's IPrincipal
It seems that there is some other way to set the IPrincipal
instance.
I have no idea about it, any good advice? By the way, why does the asp.net web api controller have no HttpContext
? Is there any design pattern about it?
The related questions ASP.NET MVC - Set custom IIdentity or IPrincipal
Just extend your
IPrincipal
.Now reference your namespace and use like this.
I implemented something as a proof of concept following mostly this: Authentication Filters in ASP.NET Web API 2
For Web API you can create an Attribute, IAuthenticationFilter. If I remember rightly, you can add it as a filter to the global filters in WebApiConfig
Or you can use it as an attribute on the api controller/ method.
You can then implement AuthenticateAsync, get the request's authorization header, check the scheme, and validate the parameter, and if all is valid, set the principal.
I think the idea is that you can add multiple of these filters in a chain and they can all authenticate against a specific set of requirements, like the scheme they look for, and somewhere in the chain the principal gets set, or a challenge is returned.
When creating the principal you can apply claims and these are checked against the normal authorize attribute. e.g.
I haven't used it beyond doing this, but hopefully this points you in the right direction.
I remember that in WebApi I could only use ControllerContext. But I'm not sure exactly why. From What I read, HttpContext is thread static, but everything in WebApi is more or less async. Take a look at this topic, maybe it will answer some questions.
This
AuthorizeAttribute
implementation worked for me. It's designed for Http Basic Auth but obviously I want to get theUser.Identity.IsAuthenticated
andUser.Identity.Name
from inside aApiController
too and this works: