Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AllowAnonymous not Working MVC5

I'm using a custom filter (defined as follows):

        if (user == null || !user.Active)
        {
            filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary
            {
                {"controller", "Home"},
                {"action", "NotAuthorized"}
            });
        }
        base.OnActionExecuting(filterContext);

This is run site-wide (in RegisterGlobalFilters() within FilterConfig.cs. However, there is one page I'd like to allow access to - the NotAuthorized page. In the HomeController, I have created the following ActionResult method:

    [AllowAnonymous]
    public ActionResult NotAuthorized()
    {
        return View();
    }

Being unauthorized does lead the user to this view, but it results in a redirect loop (likely because the filter is still being run on this page).

How can I allow anonymous users to access this page?

like image 948
muttley91 Avatar asked Apr 07 '15 18:04

muttley91


2 Answers

You need to check for the attribute in your custom filter.

Try:

if (!filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), false)
    && !filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), false)
    && (user == null || !user.Active))
{
    //....
}
like image 82
Steve Czetty Avatar answered Oct 11 '22 19:10

Steve Czetty


Check for the AllowAnonymousAttribute in your custom filter. Here is one, resuable way to do it.

Add the following extension method.

public static class MyExtensionMethods
{
    public static bool HasAttribute(this ActionExecutingContext context, Type attribute)
    {
        var actionDesc = context.ActionDescriptor;
        var controllerDesc = actionDesc.ControllerDescriptor;

        bool allowAnon = 
            actionDesc.IsDefined(attribute, true) ||
            controllerDesc.IsDefined(attribute, true);

        return allowAnon;
    }
}

Then use it in your filter.

public class MyActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // use the extension method in your filter
        if (filterContext.HasAttribute(typeof(AllowAnonymousAttribute)))
        {
            // exit early...
            return;
        }

        // ...or do whatever else you need to do
        if (user == null || !user.Active)
        {
            filterContext.Result = 
                new RedirectToRouteResult(new RouteValueDictionary
            {
                { "controller", "Home" }, 
                { "action", "NotAuthorized" }
            });
        }

        base.OnActionExecuting(filterContext);
    }
}

Here is a fiddle that implements a solution.

like image 24
Shaun Luttin Avatar answered Oct 11 '22 19:10

Shaun Luttin