23

I have a controller which should only request authorization when loaded with specific parameters. Like when the parameter ID is 8 for example.

I came up with using a custom validation attribute like this:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (/* Action's inputparameter ID = 8 */)
        {
        return base.AuthorizeCore(httpContext);
        }
        return true;
    }
}

My action looks like this (not that it is interesting)

[MyAuthorize]
public ActionResult Protected(int id)
{
    /* custom logic for setting the viewmodel from the id parameter */
    return View(viewmodel);
}

The problem is as you can see that I don't know how to check for that ID parameter in the authorize attribute. Can you help me with a solution?

vinczemarton
  • 7,756
  • 6
  • 54
  • 86

4 Answers4

33

If the id is passed as request parameter (GET or POST) or as a route data parameter:

protected override bool AuthorizeCore(HttpContextBase httpContext)
{
    // first look at routedata then at request parameter:
    var id = (httpContext.Request.RequestContext.RouteData.Values["id"] as string) 
             ??
             (httpContext.Request["id"] as string);
    if (id == "8")
    {
        return base.AuthorizeCore(httpContext);
    }
    return true;
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • The code is redundant, please see my solution below. – Herman Kan Jul 04 '14 at 14:29
  • @Darin, Can you please tell me if the input parameter of the action is a model, how to retrieve that model object instead of named parameters? – qurban Jun 06 '15 at 09:16
  • It sounds like you're actually looking for http://stackoverflow.com/questions/1335315/access-control-in-asp-net-mvc-depending-on-input-parameters-service-layer – Worthy7 Jan 11 '17 at 02:29
10

As long as AuthorizeAttribute is being inherited, you can get your parameter from AuthorizationContext, as follows:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        string idParam = filterContext.Controller.ValueProvider.GetValue("id").AttemptedValue;
        int id;

        if (int.TryParse(idParam, out id))
        {
            if (id == 8) // apply your business logic here
                return;
        }

        filterContext.Result = new HttpUnauthorizedResult();
    }
}

[MyAuthorize]
public ActionResult Protected(int id)
{
    return View();
}

The ValueProvider will iterate through all registered providers that by default includes RouteDataValueProvider, QueryStringValueProvider and FormValueProvider, and do all the work for you.

Otherwise I recommend using ActionFilterAttribute.

Herman Kan
  • 2,253
  • 1
  • 25
  • 32
  • This does not fully answer my question. I wanted to enable/disable authorization depending on the value of the `id` parameter. Is there a way to affect the Authorization from the `OnAuthorization` handler? Can you elaborate on the `...` part of your answer? – vinczemarton Jul 04 '14 at 14:47
  • @SoonDead, I changed my example. As you can see, it is still quite simple, yet fully functional. – Herman Kan Jul 08 '14 at 11:54
2

You need something like this.

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        int? id = GetId(filterContext);

        if (id.HasValue)
        {
          ...
        }
    }

    private static int? GetId(ActionExecutingContext filterContext)
    {
        int? Id = null;

        if (filterContext.ActionParameters.ContainsKey("Id"))
        {
            Id = (int?)filterContext.ActionParameters["Id"];
        }
    }
4imble
  • 13,979
  • 15
  • 70
  • 125
  • 1
    Yeah something like that, but I have a HttpContextBase parameter in the AuthorizeCore method, not an ActionExecutingContext. And I don't know how can I write authorization logic in the OnActionExecuting method. – vinczemarton Apr 05 '11 at 14:35
  • 2
    Here is a great article explaining how to access ActionParameters for authorization purposes: http://www.joe-stevens.com/2010/08/19/asp-net-mvc-authorize-attribute-using-action-parameters-with-the-actionfilterattribute/ – Michael La Voie Apr 17 '13 at 18:06
1
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var rd = httpContext.Request.RequestContext.RouteData;
        string currentAction = rd.GetRequiredString("action");
        string actionparam =Convert.ToString(rd.Values["param"]);

        if (id == actionparam)
        {
            return base.AuthorizeCore(httpContext);
        }
return true;
 }