I'm dealing with a scenario whereby I check record ownership with an ActionFilterAttribute
in a way that requires I pass through the model type the action is dealing with as well as an id parameter, like this:
[CheckOwnership(objectId = "clientid", Model = typeof(Client))]
and then run a check to see if the user's companyId matches the record's companyId, like this:
public class CheckOwnership : ActionFilterAttribute
{
public string objectId { get; set; }
public object Model { get; set; }
private MyDatabaseContext db = new MyDatabaseContext();
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.ActionParameters.ContainsKey(objectId))
{
var id = filterContext.ActionParameters[objectId] as Int32?;
var model = Model;
if (model.GetType() == typeof(Client))
{
var companyId = SharedLogic.GetCurrentCompanyId();
var clientCompanyId = db.Clients.Find(id).CompanyId;
if (companyId != clientCompanyId)
{
// deauthorize user
}
}
}
}
}
The issues lies in "deauthorizing" the user if they don't own that record in the same fashion as the [Authorize]
attribute does, by returning the user to the login page.
The only way I know how to do this is to build a custom AuthorizeAttribute
but this doesn't allow me to access the id parameter that is passed to the method when the user makes the request. By using ActionFilterAttribute
I get access to the ActionExecutingContext which I can use to retrieve parameters etc.
Is there a way to deauthorize the user and return them to the login page without using the authorize attribute?
You should use AuthorizeAttribute
and not a ActionFilterAttribute
.
The reason that you can't access model is that authorization runs before model binder so the model does not exist when attiribute's OnAuthorization
method is executed. But yo can access all the model properties that passed to the server in OnAuthorization
method like this:
public override void OnAuthorization(AuthorizationContext filterContext)
{
var rawid = filterContext.Controller.ValueProvider.GetValue("id");
if(!string.IsNullOrEmpty(rawid.AttemptedValue))
{
int id = rawid.ConvertTo(typeof(int))
}
// in case that user is unauthorized:
filterContext.Result = new HttpUnauthorizedResult();
}