ASP.NET Web API : Correct way to return a 401/unauthorised response

I have an MVC webapi site that uses OAuth/token authentication to authenticate requests. All the relevant controllers have the right attributes, and authentication is working ok.

The problem is that not all of the request can be authorised in the scope of an attribute - some authorisation checks have to be performed in code that is called by controller methods - what is the correct way to return a 401 unauthorised response in this case?

I have tried throw new HttpException(401, "Unauthorized access");, but when I do this the response status code is 500 and I get also get a stack trace. Even in our logging DelegatingHandler we can see that the response is 500, not 401.


You should be throwing a HttpResponseException from your API method, not HttpException:

throw new HttpResponseException(HttpStatusCode.Unauthorized);

Or, if you want to supply a custom message:

var msg = new HttpResponseMessage(HttpStatusCode.Unauthorized) { ReasonPhrase = "Oops!!!" };
throw new HttpResponseException(msg);

Just return the following:

return Unauthorized();

As an alternative to the other answers, you can also use this code if you want to return an IActionResult within an ASP.NET controller.

ASP.NET

 return Content(HttpStatusCode.Unauthorized, "My error message");

Update: ASP.NET Core

Above code does not work in ASP.NET Core, you can use one of these instead:

 return StatusCode((int)System.Net.HttpStatusCode.Unauthorized, "My error message");
 return StatusCode(Microsoft.AspNetCore.Http.StatusCodes.Status401Unauthorized, "My error message");
 return StatusCode(401, "My error message");

Apparently the reason phrase is pretty optional (Can an HTTP response omit the Reason-Phrase?)


You get a 500 response code because you're throwing an exception (the HttpException) which indicates some kind of server error, this is the wrong approach.

Just set the response status code .e.g

Response.StatusCode = (int)HttpStatusCode.Unauthorized;

To add to an existing answer in ASP.NET Core >= 1.0 you can

return Unauthorized();

return Unauthorized(object value);

To pass info to the client you can do a call like this:

return Unauthorized(new { Ok = false, Code = Constants.INVALID_CREDENTIALS, ...});

On the client besides the 401 response you will have the passed data too. For example on most clients you can await response.json() to get it.