ASP.Net Identity 2 - Why doesn't my filter work?

540 views Asked by At

I've tried creating an easy filter to see if the user is in a role called "System Administrator", basically short hand for having to do [Authorize(Roles = "System Administrator")]. I thought it would be fairly simple, but I'm also fairly new to MVC so perhaps I'm overlooking something.

Here's my code:

using System.Web.Mvc;

namespace site_redesign_web.Filters
{
    public class SystemAdminFilter : ActionFilterAttribute
    {
        string SysAdminRole = "System Administrator";

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.RequestContext.HttpContext.User != null)
            {
                var userSysAdmin = filterContext.RequestContext.HttpContext.User.IsInRole(SysAdminRole) == true;
                filterContext.ActionParameters["IsSysAdmin"] = userSysAdmin;
            }
        }
    }
}

Can some one suggest where am I going wrong? A huge plus would be if the person isn't a System Administrator it would direct them to Home/NoPermissions.

Thank you!

2

There are 2 answers

10
Aravind On BEST ANSWER

Updated: Fixing all issues. AJ. Here you go... Finally fixed the problem

using ActionFilterAttribute 
using System.Web.Mvc;
namespace site_redesign_web.Filters
{
    public class SystemAdminFilter : ActionFilterAttribute
    {
        string SysAdminRole = "System Administrator";
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.RequestContext.HttpContext.User != null)
            {
                var userSysAdmin = filterContext.RequestContext.HttpContext.User.IsInRole(SysAdminRole) == true;

            if(!userSysAdmin)
            {
                filterContext.Result = new RedirectToRouteResult(
                    new System.Web.Routing.RouteValueDictionary{
                    {"controller", "Home"},     
                    {"action", "Index"}
                });
            }
            }
        }
    }
}

and your Controller should be

[SystemAdminFilter]     // at controller level
public SomeController : Controller
{

}

or you can also use it for a particular Action by annotating like this

public SomeController : Controller
{
    [SystemAdminFilter]     // at Action level
    public ActionResult SomeAction()
    {
            // perform your actions
    }

It will work because I manually passed in the User with his role in the Application_AuthorizeRequest in Global.asax

protected void Application_AuthorizeRequest(Object sender, EventArgs e)
{
     FormsAuthenticationTicket formsAuthenticationTicket = new FormsAuthenticationTicket("Aravind", true, 30);
     FormsIdentity formsIdentityId = new FormsIdentity(formsAuthenticationTicket);
     GenericPrincipal genericPrincipal = new GenericPrincipal(formsIdentityId, new string[] { "SystemUser" }); //TEST with this redirected to Home Index place
     HttpContext.Current.User = genericPrincipal ;
}

The next test I made was with this

GenericPrincipal genericPrincipal = new GenericPrincipal(formsIdentityId, new string[] { "System Administrator" }); //TEST with this did not perform an action
5
Alex Art. On

Since you are dealing with authorization, I would extend AuthorizeAttribute instead of ActionFilterAttribute which is mode general. You need to override only one method - HandleUnauthorizedRequest which is executed when authorization fails. Default implementation of AuthorizeAttribute already handles role based authorization for you.

public class SystemAdminAttribute : AuthorizeAttribute
{
    private const string SysAdminRole = "System Administrator";

    public SystemAdminFilter()
    {   
        //this defines the role that will be used to authorize the user:
        this.Roles = SysAdminRole;
    }  

    //if user is not authorized redirect to "Home/NoPermissions" page
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if(!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
        else
        {
            filterContext.Result = new RedirectToRouteResult(new
               RouteValueDictionary(new { controller = "Home", action = "NoPermissions" }));
         }
     }           
}

Once your attribute is implemented, decorate corresponding Controllers or Actions with it:

[SystemAdmin]
public SysAdminController : Controller
{
}