By GoatInTheMachine


2015-07-03 11:20:16 8 Comments

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.

8 comments

@Kamrul Hasan 2019-10-30 13:48:48

You also follow this code:

var response = new HttpResponseMessage(HttpStatusCode.NotFound)
{
      Content = new StringContent("Users doesn't exist", System.Text.Encoding.UTF8, "text/plain"),
      StatusCode = HttpStatusCode.NotFound
 }
 throw new HttpResponseException(response);

@mattbloke 2019-10-30 13:30:54

In .Net Core You can use

return new ForbidResult();

instead of

return Unauthorized();

which has the advantage to redirecting to the default unauthorized page (Account/AccessDenied) rather than giving a straight 401

to change the default location modify your startup.cs

services.AddAuthentication(options =>...)
            .AddOpenIdConnect(options =>...)
            .AddCookie(options =>
            {
                options.AccessDeniedPath = "/path/unauthorized";

            })

@Gabriel P. 2019-09-28 11:33:01

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.

@AminRostami 2019-06-12 10:39:36

you can use follow code in asp.net core 2.0:

public IActionResult index()
{
     return new ContentResult() { Content = "My error message", StatusCode = (int)HttpStatusCode.Unauthorized };
}

@Alex AIT 2018-02-14 11:15:27

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(401, "My error message");

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

@Dai 2018-09-07 23:54:11

This no-longer works in ASP.NET Core, the ControllerBase class (used by ASP.NET Core WebAPI) no-longer has a Content overload that accepts a HTTP status code.

@Nick Turner 2019-01-02 20:19:01

This is wrong. A Content response is a 200 Ok status. The server should send a 401 and the client should handle accordingly. You can't send a 200 as a 401. It doesn't make sense. If the client gets a 401, it's not an Oops, it's a your breaking the law.

@Alex AIT 2019-01-02 21:39:51

This code is sending a 401 status code(HttpStatusCode.Unauthorized), not 200. Content(...) simply a shorthand for returning any given content with a given HTTP status code. If you want to send 200 you can use Ok(...)

@Chris F Carroll 2019-04-09 13:36:42

@NickTurner -- that's an argument for the webapi2 Content() method being poorly named not for this being the wrong answer. Since the (status,message) method is renamed in NetCore, I guess the devs agree it was poorly named.

@JohnWrensby 2016-08-01 20:39:39

Just return the following:

return Unauthorized();

@JohnWrensby 2016-12-18 21:34:08

I think the accepted answers the OP's question specifically. My answer answers the question's title "ASP.NET Web API : Correct way to return a 401/unauthorised response"

@Simon_Weaver 2018-07-09 08:07:45

Anybody know why there's no overloaded version of this with a message?

@Rikki 2018-09-17 18:03:19

@Simon_Weaver No idea why, but you could use a return Content<string>(HttpStatusCode.Unauthorized, "Message"); to do this.

@Nick Turner 2019-01-02 20:15:03

This should be the correct answer. 1 it is correct. 2) If this changes in a later framework, you don't have to change code. 3) You don't need to provide a reason to a 401. This should be handled by the client and not the server.

@Nae 2019-05-13 11:46:12

Which library is this in?

@LukeH 2015-07-03 12:26:20

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);

@DGibbs 2015-07-03 11:28:36

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;

@GoatInTheMachine 2015-07-03 12:06:12

It's a bit odd then that the exception takes the HTTP status code as a parameter, and intellisense docs say that this is the status code sent to the client - I was hoping to avoid mutating the response myself directly as this seems error prone, seeing as its global state

@LukeH 2015-07-03 12:07:48

The base Web API controller doesn't expose a Response property.

Related Questions

Sponsored Content

11 Answered Questions

[SOLVED] Best practice to return errors in ASP.NET Web API

15 Answered Questions

1 Answered Questions

Cookie authentication for MVC and OAuth for WebAPI in the same app

1 Answered Questions

[SOLVED] How to log "unauthorized" (401) response

  • 2019-01-11 17:51:29
  • Mat
  • 161 View
  • 1 Score
  • 1 Answer
  • Tags:   c# asp.net-core

1 Answered Questions

How to get 401 response from identityServer4

4 Answered Questions

Sponsored Content