Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

401 response code for json requests with ASP.NET MVC

Tags:

asp.net-mvc

How to disable standard ASP.NET handling of 401 response code (redirecting to login page) for AJAX/JSON requests?

For web-pages it's okay, but for AJAX I need to get right 401 error code instead of good looking 302/200 for login page.

Update: There are several solutions from Phil Haack, PM of ASP.NET MVC - http://haacked.com/archive/2011/10/04/prevent-forms-authentication-login-page-redirect-when-you-donrsquot-want.aspx

like image 253
derigel Avatar asked Sep 23 '08 20:09

derigel


3 Answers

In classic ASP.NET you get a 401 http response code when calling a WebMethod with Ajax. I hope they'll change it in future versions of ASP.NET MVC. Right now I'm using this hack:

protected void Application_EndRequest()
{
    if (Context.Response.StatusCode == 302 && Context.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
    {
        Context.Response.Clear();
        Context.Response.StatusCode = 401;
    }
}
like image 102
Catalin DICU Avatar answered Nov 18 '22 15:11

Catalin DICU


The ASP.NET runtime is developed so that it always will redirect the user if the HttpResponse.StatusCode is set to 401, but only if the <authentication /> section of the Web.config is found.

Removing the authentication section will require you to implement the redirection to the login page in your attribute, but this shouldn't be a big deal.

like image 40
Troels Thomsen Avatar answered Nov 18 '22 15:11

Troels Thomsen


I wanted both Forms authentication and to return a 401 for Ajax requests that were not authenticated.

In the end, I created a custom AuthorizeAttribute and decorated the controller methods. (This is on .Net 4.5)

//web.config

<authentication mode="Forms">
</authentication>

//controller

[Authorize(Roles = "Administrator,User"), Response302to401]
[AcceptVerbs("Get")]
public async Task<JsonResult> GetDocuments()
{
    string requestUri = User.Identity.Name.ToLower() + "/document";
    RequestKeyHttpClient<IEnumerable<DocumentModel>, string> client =
        new RequestKeyHttpClient<IEnumerable<DocumentModel>, string>(requestUri);

    var documents = await client.GetManyAsync<IEnumerable<DocumentModel>>();

    return Json(documents, JsonRequestBehavior.AllowGet);
}

//authorizeAttribute

public class Response302to401 : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.Result = new JsonResult
                {
                    Data = new { Message = "Your session has died a terrible and gruesome death" },
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet
                };
                filterContext.HttpContext.Response.StatusCode = 401;
                filterContext.HttpContext.Response.StatusDescription = "Humans and robots must authenticate";
                filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
            }
        }
        //base.HandleUnauthorizedRequest(filterContext);
    }
}
like image 9
Timothy Lee Russell Avatar answered Nov 18 '22 15:11

Timothy Lee Russell