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?

4 Answers 4

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;
}
Sign up to request clarification or add additional context in comments.

3 Comments

The code is redundant, please see my solution below.
@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?
It sounds like you're actually looking for stackoverflow.com/questions/1335315/…
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.

2 Comments

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?
@SoonDead, I changed my example. As you can see, it is still quite simple, yet fully functional.
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"];
        }
    }

2 Comments

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.
Here is a great article explaining how to access ActionParameters for authorization purposes: joe-stevens.com/2010/08/19/…
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;
 }

1 Comment

How does this differ from Darin Dimitrov's answer exactly?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.