asp.net-mvcasp.net-mvc-5asp.net-identityasp.net-mvc-filters

Changing ModelState when authorization fails


I have written a custom Authorize Filter:

public class MyAuthenticationAttribute : FilterAttribute, IAuthorizationFilter{

    // Do the authorization    
    if (!isAuthenticated)
    {
        filterContext.Result = new HttpUnauthorizedResult();
    }
}

This filter has various conditions and in the end will set the result to Unauthorized, if the user is not authorized and will do nothing if the user is authorized.

It's being used in a SPA application and almost all of my methods are called from grids. In those Grids I have custom error handler that will show friendly notifications if something goes wrong. All of the errors are added to the ModelState.

Now, I'd like to manage unauthorized behavior and change ModelState when user is not authorized to do for example delete.

Please guide me how should I implement it and what methods I need to override.

UPDATE

I can change model state with this line:

filterContext.Controller.ViewData.ModelState.AddModelError("", "GO AWAY!");

But it doesn't return anything to the user. I've tried using IAuthenticationFilter and adding ModelState error in the challenge method, and it didn't work neither.

I guess it'll work fine if I could return some Json data.

I need to somehow get similar behavior of this action method:

public ActionResult Delete([DataSourceRequest] DataSourceRequest request, object model)
{
    ModelState.AddModelError("", "error");
    return Json(new[] { model}.ToDataSourceResult(request, ModelState));
}

Is it possible? Do you have any suggestion about implementing this authorization and returning Json data?


Solution

  • You can return any result you want by using context.Result, in my case I'd like to cancel Kendo Grid's changes and add a model state error that I achieved with this code:

    public void OnAuthenticationChallenge(AuthenticationChallengeContext context)
    {
        if (context.Result == null || context.Result is HttpUnauthorizedResult)
        {
            var ModelState = context.Controller.ViewData.ModelState;
    
            context.Result = new JsonResult
            {
                Data = new Kendo.Mvc.UI.DataSourceResult
                {
                    Errors = ModelState.SerializeErrors()
                }
            };
        }
    }