Always success on ajax post with HttpResponseMessage 401 Always success on ajax post with HttpResponseMessage 401 ajax ajax

Always success on ajax post with HttpResponseMessage 401


Because a status of 200 is being returned, but the user is not authorized, another option is to check for X-Responded-JSON with a status of 401 in your javascript.

.done(function (object, status, xhr) {      if (xhr.getResponseHeader("X-Responded-JSON") != null           && JSON.parse(xhr.getResponseHeader("X-Responded-JSON")).status == "401") {          //some message here          return;     }}


It might be that your page is redirecting to a login page by the forms authentication module as soon as you return HttpStatusCode.Unauthorized.

From MSDN:

All unauthenticated users are denied access to any page in your application. If an unauthenticated user tries to access a page, the forms authentication module redirects the user to the logon page specified by the loginUrl attribute of the forms element.

The login page, or whatever page it's being redirected to, is then served with status code 200.


To elaborate on Valin's comment, and inline Brock Allen's solution.

The clue lies in the returned OK response which internally traps the redirect to a form login:

X-Responded-JSON: {"status": 401, "headers": {"location":"http:\/\/localhost:50004\/Login?ReturnUrl=%2FClient"}}

If you'd like to fix on the server, instead of scraping the response for this internal error state, you can use the solution from Brock Allen's article on Using cookie authentication middleware with Web API and 401 response codes:

Normally when using cookie authentication middleware, when the server (MVC or WebForms) issues a 401, then the response is converted to a 302 redirect to the login page (as configured by the LoginPath on the CookieAuthenticationOptions). But when an Ajax call is made and the response is a 401, it would not make sense to return a 302 redirect to the login page. Instead you’d just expect the 401 response to be returned. Unfortunately this is not the behavior we get with the cookie middleware — the response is changed to a 200 status code with a JSON response body with a message:

{"Message":"Authorization has been denied for this request."}

I’m not sure what the requirement was for this feature. To alter it, you must take over control of the behavior when there is a 401 unauthorized response by configuring a CookieAuthenticationProvider on the cookie authentication middleware:

app.UseCookieAuthentication(new CookieAuthenticationOptions{   AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,   LoginPath = new PathString("/Account/Login"),   Provider = new CookieAuthenticationProvider   {      OnApplyRedirect = ctx =>      {         if (!IsAjaxRequest(ctx.Request))         {            ctx.Response.Redirect(ctx.RedirectUri);         }     }   }});

Notice it handles the OnApplyRedirect event. When the call is not an Ajax call, we redirect. Otherwise, we do nothing which allows the 401 to be returned to the caller.

The check for IsAjaxRequest is simply copied from a helper in the katana project:

private static bool IsAjaxRequest(IOwinRequest request){   IReadableStringCollection query = request.Query;   if ((query != null) && (query["X-Requested-With"] == "XMLHttpRequest"))   {      return true;   }   IHeaderDictionary headers = request.Headers;   return ((headers != null) && (headers["X-Requested-With"] == "XMLHttpRequest"));}