Using an MVC4 application using .NET 4.5 and IIS 8. Is there a way to return a custom unauthorized page and result 401 when the permission check failed?
I also use authentication on Forms and want to redirect to the login page when the user is not logged in, but redirected to the unauthorized page when the user does not have valid permission (for example, Admin).
I also have to be careful in redirecting and then achieving a 200/301 result on successful redirection.
I need to return the status code 401 and stay on the current page, as well as return a user unauthorized page.
I have an error controller that returns an unauthorized view:
[ActionName("unauthorised")] public ActionResult Http401() { Response.StatusCode = 401; Response.StatusDescription = "Unauthorised"; Response.SuppressFormsAuthenticationRedirect = true; return View("unauthorised"); }
And I have some methods that I use to try and call 401 if the permission check fails:
/// <summary>Method to invoke when user attempts action without relevant permission</summary> /// <param name="httpContext">the httpcontext</param> /// <returns>empty result</returns> public ActionResult InvokeHttp401(HttpContextBase httpContext) { Transfer("/error/unauthorised"); return new EmptyResult(); } private void Transfer(string url) { var uriBuilder = new UriBuilder(Request.Url.Scheme, Request.Url.Host, Request.Url.Port, Request.ApplicationPath); // Create URI builder uriBuilder.Path += url; // Add destination URI string path = Server.UrlDecode(uriBuilder.Uri.PathAndQuery); // Because UriBuilder escapes URI decode before passing as an argument this.HttpContext.RewritePath(path, false); // Rewrite path HttpContext.Server.TransferRequest(path, true); }
Note. I am using Server.TransferRequest to try to return a 401 result to the current URL without causing a redirect. I check the resolution in a regular ActionResult as follows:
[Authorize] public ActionResult MyMethod() { if (!UserHasPermission(Admin)) return InvokeHttp401(HttpContext); ......
If the authorization tag is redirected to the login, if the user is not logged in, another check of rights is performed.
With the setting above, I can return the result 401 and stay at the current URL, but IIS 401 error is displayed instead of the current page.
I also tried installing the following in my web.config file:
<httpErrors errorMode="DetailedLocalOnly" existingResponse="Replace"> ..... <error statusCode="401" responseMode="ExecuteURL" path="/Error/unauthorised" /> </httpErrors>
But it does not matter. I can get a custom unauthorized page if I do not set a status code in my Http401 ActionResult, but it just returns with a result of 200.
I looked at the posts on this question (in particular, Timofeyโs answer, which expanded the authorization tags), but I could not get any of these actions without similar ones as already described.
Can anyone help here?