I have a standard VS2013 MVC5 project with a Web Api 2 in it. The way the standard project is designed, the [Authorize] attributes simply return a 401 status code if the request is not authenticated, while a totally separate module sniffs for any 401 codes, halts them, and instead sends a 302 redirect to the login page specified in the Startup.Auth.cs file. That's ok for Mvc controllers, but really stinks for Web Api controllers because for example browsers will automatically redirect ajax requests to the login url, so you ultimately end up with a 200OK status even though the response text is just the html of the login page.
That makes it hard to write good javascript that can distinguish between a case where you just need to tell the user to log back in versus other kinds of errors. Ideally we should be able to tell based on the status code, but javascript never ever sees the 401 status. What is the best way to handle this?
My first thought was to write an authorization attribute but use status code 403 instead of 401:
public class ApiAuthorizationAttribute : System.Web.Http.AuthorizeAttribute
{
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (actionContext.RequestContext.Principal.Identity.IsAuthenticated)
{
base.OnAuthorization(actionContext);
}
else
{
actionContext.Response = actionContext.ControllerContext.Request.CreateErrorResponse(HttpStatusCode.Forbidden, "Not signed in.");
}
}
}
Of course, specifications explicitly state that 403 is incorrect:
Authorization will not help and the request SHOULD NOT be repeated
My other thought is that maybe I should disable asp.net's 401 redirect module altogether and handle redirects in custom authorization attributes, because even for Mvc views it is lousy because it doesn't allow you to redirect to different login pages depending on where in the site the user is trying to visit.
Are there other, better approaches to handling this?