0

I have an intranet application setup with windows authentication. Like in most applications, certain parts of the application are accessible to specific roles only. When a user not in desired role would try to access that area, he should be shown a friendly "You do not have permission to view this page" view. I searched and looked at several resources that guides to extend the Authorize Attribute. I tried that approach, but it simply doesn't work. I still get the IIS error message and the breakpoint in this custom attributes never gets hit. The breakpoint in my extended attibute doen't get hit even when a user in role visits the page. So, I am wondering if I am missing anything ? This is what I have -

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeRedirect : AuthorizeAttribute
{

    private const string IS_AUTHORIZED = "isAuthorized";
    public string RedirectUrl = "~Areas/Errors/Http401";


    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        bool isAuthorized =  base.AuthorizeCore(httpContext);
        httpContext.Items.Add(IS_AUTHORIZED, isAuthorized);
        return isAuthorized;
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);

        var isAuthorized = filterContext.HttpContext.Items[IS_AUTHORIZED] != null ? Convert.ToBoolean(filterContext.HttpContext.Items[IS_AUTHORIZED]) : false;

        if(!isAuthorized && filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated)
        {
        filterContext.RequestContext.HttpContext.Response.Redirect(RedirectUrl);
        }

    }
}

CONTROLLER -

    [AuthorizeRedirect]
    [HttpPost, ValidateInput(true)]
    public  ActionResult NewPart(PartsViewModel vmodel) {..}

Any ideas?

Thanks

annantDev
  • 367
  • 4
  • 20

1 Answers1

0

I think you could use custom error pages instead. Use AuthorizeAttribute to restrict access by callers to an action method.

[Authorize (Roles="Editor, Moderator", Users="Ann, Gohn")]
public ActionResult RestrictedAction()
{
    // action logic
}

Then you could use one of the ways those are proposed by @Marco. I like handle HTTP status code within Application_EndRequest. So, it is possible to solve your problem using by following:

protected void Application_EndRequest()
{
    int status = Response.StatusCode;
    if (Response.StatusCode == 401)
    {
        Response.Clear();
        var rd = new RouteData();
        rd.DataTokens["area"] = "Areas";
        rd.Values["controller"] = "Errors";
        rd.Values["action"] = "Http401";
        IController c = new ErrorsController();
        c.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
    }
}

To clearly specifiey what happens to an existing response when the HTTP status code is an error, you should use existingResponse attribute of <httpErrors> element in your configuration file. If you want to the error page appears immediately, then use Replace value, in otherwise - PassThrough (see details in my issue).

Alexander
  • 4,420
  • 7
  • 27
  • 42