1

I'm attempting to create a custom authorize attribute in MVC4/Razor and am having an issue with the "AllowAnnoymous" attribute running under the custom authorize attribute (it seems to ignore it). That's all fine and dandy, as I found a solution (see below) to that by checking if the controller or action contain an allow anonymous attribute and then allow pass through if so.

However, I'm seeing that when I create the "AuthorizeAttribute" class and attempt to implement "OnAuthorization" override, it sets the object handlers to a type of "AuthorizationContext" but in the below example and many others i've found on here, it seems the "AuthorizationContext" should not be used - instead it should be "HttpActionContext". Though I tried to replace it with "HttpActionContext" and the override then fails saying there is no suitable method. Any ideas on what I'm missing/doing wrong?

Example Found Here (By Jammer)

private static bool SkipAuthorization(HttpActionContext actionContext)
{
    Contract.Assert(actionContext != null);

    return actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any()
               || actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any();
}

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

My Code

private override void OnAuthorization(AuthorizationContext filterContext) // Not sure how to change this to HttpActionContext
{
    if (filterContext == null) throw new ArugmentException("filterContext");
    if (!AllowAnnonymous(new HttpActionContext()))
    {
        throw new HttpResponseException(HttpStatusCode.UnAuthorized);
    }
    else
    {
        base.OnAuthorization(filterContext);
    }
}
sys_adm_dev
  • 65
  • 1
  • 8

1 Answers1

3

Any ideas on what I'm missing/doing wrong?

First of all, you are looking at an example that uses the Web API System.Web.Http.AuthorizeAttribute instead of the MVC System.Web.Mvc.AuthorizeAttribute. MVC and Web API are separate frameworks and neither will recognize the other's attributes. This is also the reason why you have a different context type in your AuthorizeAttribute.

Secondly, the reason your custom AuthorizeAttribute doesn't recognize AllowAnonymousAttribute is because you are overriding the logic that does that check in OnAuthorization (along with other important logic that deals with output caching). If you instead override AuthorizeCore and return true/false, then you will not skip this important logic.

If you need to change where the user is redirected, you can override HandleUnauthorizedRequest, which only executes when authorization fails.

Finally, if you need to access the ActionDescriptor to scan for your own attributes, it is passed into OnAuthorization via AuthorizationContext.ActionDescriptor. Unfortunately, it is not passed into AuthorizeCore automatically, but you can work around this by setting it to HttpContext.Items in OnAuthorization as in this example.

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • Well - that definitely explains it. I suppose I didn't look into the different authorize attribute/didn't realize the WebAPI used a separate one from MVC. Is it possible to use the System.Web.Http.AuthorizeAttribute in this scenario vs MVC's? I will also check out the "AuthorizeCore" override, as I definitely want to be able to use the anonymous attributes (without having to hodgepodge things). I sincerely appreciate the explanation! – sys_adm_dev Dec 14 '17 at 13:15
  • `Is it possible to use the System.Web.Http.AuthorizeAttribute in this scenario vs MVC's?` No, but it is unclear why you would want to. If you want to share business logic between them, you can either create a single class that implements both `System.Web.Mvc.IAuthorizationFilter` and `System.Web.Http.IAuthorizationFilter`, or you could create a common service that is injected into both filters (see [this answer](https://stackoverflow.com/a/32254851/) for info on how to use DI with AuthorizeAttribute.). – NightOwl888 Dec 14 '17 at 18:52
  • Interesting - I think this will work for me based on my testing with the provided link/explanation. Thank you for the help! – sys_adm_dev Dec 15 '17 at 11:04