1
votes

I have a requirement for a new ASP.NET MVC application. When a user is logged into the site there is a black box that we need to call into to see if the user is allowed to use the Controller/Action.

All our controllers have the [Authorize] attribute by default (except Login), but some of the actions can only be called if a black box says the user can.

How would I get the MVC sub system (I'm guessing thru something like a custom [Authorize?]) to respond with an unauthorized response when a logged in user tries to access a Controller Action which the black box says they can't.

Here's the way we call the BlackBox:

 bool canAccess = BlackBox.HasAccess(controllerName, ActionName, userGuid);
2

2 Answers

2
votes

I suggest a custom Authorize attribute (as you already guessed).

Here is an example below:

public class BlackBoxAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        bool authorized = base.AuthorizeCore(httpContext);

        if (authorized)
        {
            var routeData = httpContext.Request.RequestContext.RouteData;
            var controller = routeData.GetRequiredString("controller");
            var action = routeData.GetRequiredString("action");

            bool canAccess = BlackBox.HasAccess(controller, action, userGuid);

            if (!canAccess)
            {
                httpContext.Items["BlackBoxError"] = true;
                return false;
            }

            return true;
        }
        else
        {
            return authorized;
        }
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        bool blackBoxError = filterContext.HttpContext.Items["BlackBoxError"] != null && Convert.ToBoolean(filterContext.HttpContext.Items["BlackBoxError"].ToString());

        if (blackBoxError)
        {
            //change the controler name and action name accordingally as needed.
            filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary
                                                                        {
                                                                            { "controller", "Error" }, 
                                                                            { "action", "BlackBoxError" } 
                                                                        }
                                                                    );
        }

        base.HandleUnauthorizedRequest(filterContext);
    }
}

With this in place you'll have to replace all AuthorizeAttribute annotations with BlackBoxAuthorizeAttribute. Or even better: remove AuthorizeAttribute from your controllers and register a global attribute in app_start.

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new BlackBoxAuthorizeAttribute());
        }

Hope this helps!

Regards, Uros

0
votes

You can try inheriting from AuthorizeAttribute and create you own attribute.

public class BlackboxAuthorizeAttribute : AuthorizeAttribute
{
 protected override bool AuthorizeCore(HttpContextBase httpContext)
 {
 //write here custom authorization logic
 }
 protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
 {

 }
}

And then use your custom authorize attribute on your controller action.