I was trying to accomplish the same thing, basically wanting to control authorization with attributes on the action method parameters, as an example:
[MyAuthorize]
public ActionResult MyAction(
[Require(Permission.Write)] MyCustomObject arg1,
[Require(Permission.Read)] MyCustomObject arg2
) {
// ... all authorization would be handled before the action is invoked ...
}
class MyAuthorize : AuthorizeAttribute {
public override void OnAuthorization(AuthorizationContext filterContext) {
// ... filterContext doesn't have the argument objects ...
}
}
I ran into the same issue, when overriding AuthorzeAttribute.OnAuthorization(...) the model bound arguments don't exist yet. To accomplish what I needed, I implemented IActionFilter which exposes a method OnActionExecuting that will be called after the model is bound but before the action is invoked. My prototype implementation looks like this:
class MyAuthorizeAttribute : AuthorizeAttribute, IActionFilter {
public override void OnAuthorization(AuthorizationContext filterContext) {
// ... I guesss this isn't really needed any more.
// the auth check is handled in OnActionExecuting.
}
void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext) {
}
void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) {
foreach (var param in filterContext.ActionDescriptor.GetParameters()) {
var attr = (RequireAttribute)param.GetCustomAttributes(typeof(RequireAttribute), false).FirstOrDefault();
if(attr != null) {
Object obj;
if (filterContext.ActionParameters.TryGetValue(param.ParameterName, out obj)) {
var sec = obj as ISecurable;
if (sec == null || !sec.HasPermission(filterContext.RequestContext, attr.Permission)) {
filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.Unauthorized);
}
}
}
}
}
}
interface ISecurable {
bool HasPermission(Permission permission);
}
This is just a proof of concept for a project I'm working on, but it seems like a workable solution.