Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AllowAnonymous not working with Custom AuthorizationAttribute

This has had me stumped for a while. None of the commonly encountered similar situations seem to apply here apparently. I've probably missed something obvious but I can't see it.

In my Mvc Web Application I use the Authorize and AllowAnonymous attributes in such a way that you have to explicitly open up an action as publicly available rather than lock down the secure areas of the site. I much prefer that approach. I cannot get the same behaviour in my WebAPI however.

I have written a custom Authorization Attribute that inherits from System.Web.Http.AuthorizeAttribute with the following:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class MyAuthorizationAttribute : System.Web.Http.AuthorizeAttribute 

I have this registered as a filter:

    public static void RegisterHttpFilters(HttpFilterCollection filters)     {         filters.Add(new MyAuthorizationAttribute());     } 

This all works as expected, actions are no longer available without credentials. The problem is that now the following method will not allow the AllowAnonymous attribute to do it's thing:

[System.Web.Http.AllowAnonymous] public class HomeController : ApiController {     [GET("/"), System.Web.Http.HttpGet]     public Link[] Index()     {         return new Link[]          {              new SelfLink(Request.RequestUri.AbsoluteUri, "api-root"),             new Link(LinkRelConstants.AuthorizationEndpoint, "OAuth/Authorize/", "authenticate"),             new Link(LinkRelConstants.AuthorizationTokenEndpoint , "OAuth/Tokens/", "auth-token-endpoint")         };     } } 

The most common scenario seems to be getting the two Authorize / AllowAnonymous attributes mixed up. System.Web.Mvc is for web apps and System.Web.Http is for WebAPI (as I understand it anyway).

Both of the Attributes I'm using are from the same namespace - System.Web.Http. I assumed that this would just inherit the base functionality and allow me to inject the code I need in the OnAuthotize method.

According to the documentation the AllowAnonymous attribute works inside the OnAuthorize method which I call immediately:

    public override void OnAuthorization(HttpActionContext actionContext)     {         base.OnAuthorization(actionContext); 

Any thought's would be really appreciated.

Has anyone encountered this problem before and found the root cause?

like image 406
Jammer Avatar asked Nov 28 '12 00:11

Jammer


People also ask

What is AllowAnonymous attribute in Web API?

One of the new features in ASP.NET MVC 4 is the AllowAnonymous Attribute that helps you secure an entire ASP.NET MVC 4 Website or Controller while providing a convenient means of allowing anonymous users access to certain controller actions, like the login and register Actions.

What is AllowAnonymous attribute in MVC?

The AllowAnonymous attribute in MVC is used to skip the authorization which is enforced by Authorization Filter in MVC. [AllowAnonymous] public ActionResult NonSecured() { return View();

What is the use of AllowAnonymous?

AllowAnonymous lets users who have not been authenticated access the action or controller. In short, it knows based on the token it receives from the client.


2 Answers

In the AuthorizeAttribute there is the following code:

private static bool SkipAuthorization(HttpActionContext actionContext) {     Contract.Assert(actionContext != null);      return actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any()                || actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any(); } 

Include this method in your AuthorizeAttribute class then add the following to the top of your OnAuthorization method to skip authorization if any AllowAnonymous attributes are found:

if (SkipAuthorization(actionContext)) return; 
like image 59
Jammer Avatar answered Oct 04 '22 20:10

Jammer


ASP.NET MVC 4:

bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true)                          || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true); 

or

 private static bool SkipAuthorization(AuthorizationContext filterContext)     {         Contract.Assert(filterContext != null);          return filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), true).Any()                || filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), true).Any();     } 

Soruce: http://weblogs.asp.net/jongalloway/asp-net-mvc-authentication-global-authentication-and-allow-anonymous

like image 36
g.breeze Avatar answered Oct 04 '22 20:10

g.breeze