11

I have a controller with an Authorize attribute like this:

[Authorize(Roles = "Viewer")]
public class HomeController : Controller
{
   //...
}

and my web.config has customErrors set like the following:

<customErrors mode="On">
      <error statusCode="401" redirect="notauthorized.html"/>
  </customErrors>

When I try to invoke an action on the Home controller using a non-authorized role I just get a blank page. I don't get redirected to the custom page. Any ideas?

Marco M.
  • 2,956
  • 2
  • 29
  • 22

4 Answers4

14

I appreciate this question is a little old, but this may help someone.

For a 401 you will probably be seeing the standard 401 Unauthorised page, even if you have added 401 to the customerrors section in your web.config. I read that when using IIS and Windows Authentication the check happens before ASP.NET even sees the request, hence you see the blank page on Cassini and on IIS it's own 401.

For my project I edited the Global.asax file to redirect to a route I had created for 401 errors, sending the user to the "Unauthorised to see this" view.

In the Global.asax:

    void Application_EndRequest(object sender, System.EventArgs e)
    {
        // If the user is not authorised to see this page or access this function, send them to the error page.
        if (Response.StatusCode == 401)
        {
            Response.ClearContent();
            Response.RedirectToRoute("ErrorHandler", (RouteTable.Routes["ErrorHandler"] as Route).Defaults);
        }
    }

and in the Route.config:

        routes.MapRoute(
        "ErrorHandler",
        "Error/{action}/{errMsg}",
        new { controller = "Error", action = "Unauthorised", errMsg = UrlParameter.Optional }
        );

and in the controller:

    public ViewResult Unauthorised()
    {
        //Response.StatusCode = 401; // Do not set this or else you get a redirect loop
        return View();
    }
VictorySaber
  • 3,084
  • 1
  • 27
  • 45
3

Take a look at tvanfosson's Answer from this very similar question, This is what I am doing(Thanks to tvanfosson), so now I just have to say:

[MyAuthorize(Roles="SuperAdmin",ViewName="AccessDenied")]
public class SuperAdminController : Controller
...

If the user is not in the role, they will get thew view specified by ViewName.

Note: the blank page is coming from Cassini, if you move the app to an actual IIS server you will see the 401.

Community
  • 1
  • 1
KP.
  • 2,138
  • 23
  • 21
  • you mean if i move the app to IIS i should see the custom page? or i should just see the standard IIS 401 page? – Marco M. Sep 14 '09 at 17:29
1

A standard approach as far as I know is to have a simple error controller that handles incoming requests and outputs the appropriate view depending on which httpstatus code was returned... something like this:

  public class ErrorController : Controller
{

    [AcceptVerbs(HttpVerbs.Get)]
    public ViewResult Index()
    {

        //Check if the statuscode is HttpStatusCode.NotFound;
         if(Response.StatusCode == 401)
             return View("NotAuthorised");
        return View();
    }
}

and then specify a redirect action in your webconfig:

<customErrors mode="On" defaultRedirect="~/Error" />
Robban
  • 6,729
  • 2
  • 39
  • 47
0

Also you can create your own custom authorization attribute and set your own route to redirect users on your page.

Here a sample on my project:

/*../controllers/CustomAuthorizationAttribute.cs  */
public class CustomAuthorizationAttribute : FilterAttribute, IAuthorizationFilter
{
    void IAuthorizationFilter.OnAuthorization(AuthorizationContext filterContext)
    {
        string session = filterContext.HttpContext.Session["id"] != null ? filterContext.HttpContext.Session["id"].ToString() : null;
        if ( string.IsNullOrEmpty(session) )
        {
            // Unauthorized!
            filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary
                {
                    { "action", "Create" }, { "controller", "Sessions" } 
                    //,{ "parameterName", "YourParameterValue" }
                }
            );
        }
    }
}

and you add your "flag" in your action controller like this

/*../controllers/ReportsController.cs  */
public class ReportsController : Controller
{
    [CustomAuthorizationAttribute]
    public ActionResult Index()
    {
        //do something
    }
}
alexandre-rousseau
  • 2,321
  • 26
  • 33