9

I have an ASP.NET Core Web API 3 app that implements a REST API and uses a JWT bearer token for authorization, and Swagger (Swashbuckle).

My controller has the [Authorize] filter on it, like:

[ApiController]
[Route("api/[controller]")]
[Authorize]
public class MyController : ControllerBase
{
}

Swagger works with my API, and I can generate a JWT token and give to Swagger and it all works well.

But if I try to use Swagger to hit one of my REST endpoints without a JWT token or invalid JWT token, the Swagger UI is showing an error 401 Undocumented, but all the examples I see out on the web show that I should be getting 401 Unauthorized.

(When I hit the same URL with Postman, it does show 401 Unauthorized.)

Before I start ripping out things, any ideas why I might be getting Undocumented instead of Unauthorized?

This is what I see:

enter image description here

When I add the attribute suggested below

 (ProducesResponseType(typeof(ProblemDetails), (int)HttpStatusCode.Unauthorized)])

I see this:

enter image description here

JoeD
  • 203
  • 1
  • 4
  • 8
  • It looks like it's working exactly as intended... I do not see an error here, if you have any concerns report in on the project: https://github.com/swagger-api/swagger-ui/issues/new/choose – Helder Sepulveda Apr 12 '20 at 16:49
  • 1
    Did you manage to solve this problem ? I have same issue now – DespeiL Feb 24 '21 at 12:04
  • @HelderSepulveda is working fine, yes, but in the _Details_ column, in _Error:_ should say "Unauthorized". Here is an image of the missing behavior JoeD is reporting: [link](https://csharpcorner.azureedge.net/article/authentication-and-authorization-in-asp-net-5-with-jwt-and-swagger/Images/04%20Unauthorized%20Error.png) – cesAR Mar 07 '21 at 14:52
  • I have the same issue. In one of my APIs it prints "Error:" only just like yours, in another it prints "Error: Unauthorized". I want them both print "Error: Unauthorized". I have operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" }); in IOperationFilter but changing or removing description does not help. – Meeting Attender Jun 22 '21 at 13:29

4 Answers4

6

You can add app.UseStatusCodePages() in the Startup.cs.

This will then return a response body response body

Marian Nasry
  • 821
  • 9
  • 22
3

Maybe it is late, but I was into this problem so now I'll answer that.

It shows Undocumented because there is no bearer keyword existing at the beginning of your Authorization header. Probably your header is something like this:

Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJNb3N0YWZhOTEiLCJqdGkiOiIzNGEzNjQwNC1iZWNjLTRhMmMtOGJkZi01ZDc1ZTBiY2QwZGIiLCJJZCI6IjEiLCJleHAiOjE2MTAyNDcyMTUsImlzcyI6Im1vaGFtYWRyYXZhZWkuaW5mbyIsImF1ZCI6Im1vaGFtYWRyYXZhZWkuaW5mbyJ9.0_kKI7F12o62A_QUZ38U9KVbBpnQMyO7kGcqBZzU4AU

so you should change it to:

Authorization: 
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJNb3N0YWZhOTEiLCJqdGkiOiIzNGEzNjQwNC1iZWNjLTRhMmMtOGJkZi01ZDc1ZTBiY2QwZGIiLCJJZCI6IjEiLCJleHAiOjE2MTAyNDcyMTUsImlzcyI6Im1vaGFtYWRyYXZhZWkuaW5mbyIsImF1ZCI6Im1vaGFtYWRyYXZhZWkuaW5mbyJ9.0_kKI7F12o62A_QUZ38U9KVbBpnQMyO7kGcqBZzU4AU

Actually Postman set the bearer at the beginning of Token and if you set Bearer but the Token is deprecated then the status code is going to show Unauthorized code.

jaygeek
  • 1,004
  • 10
  • 14
Ravaei
  • 8
  • 6
  • 1
    I'm facing the problem exactly as @JoeD reported. I'm unable to follow you indications, what are you referring with "start point of you Authorization header"? I'm on .Net 5, and everything works fine, just that little thing on Swagger. Thanks! – cesAR Mar 07 '21 at 02:34
  • @cecAR Did you add the Bearer before the Token in the header of your request? – Ravaei Mar 08 '21 at 23:24
  • Now I understand what you mean. There is no problem authenticating, that part is working fine (no need even to add the _bearer_ word). The problem is, when you are not authenticated. The interface must show on the _Details_ box, "Error: unauthorized". Here I let you an image that explain what is missing: [link](https://csharpcorner.azureedge.net/article/authentication-and-authorization-in-asp-net-5-with-jwt-and-swagger/Images/04%20Unauthorized%20Error.png) – cesAR Mar 09 '21 at 12:56
3

any ideas why I might be getting Undocumented instead of Unauthorized?

Well because it's not documented by Swashbuckle.

One basically has two options:

Option one: Use XML-Comments on every [Authorize] endpoint, here is an example:

/// <summary>
/// StackOverflow example
/// </summary>
/// <response code="200">All good here</response>
/// <response code="401">Unauthorized</response>
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class MyController : ControllerBase
{

}

And implement Include descriptions from XML comments like this.

Option two: Use an operation filter once to add it to all [Authorized] endpoints:

Create a new class:

// using Microsoft.AspNetCore.Authorization;
// using Microsoft.OpenApi.Models;
// using Swashbuckle.AspNetCore.SwaggerGen;
public class AuthResponsesOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        if (context != default && context.MethodInfo != default && context.MethodInfo.DeclaringType != default)
        {
            IEnumerable<AuthorizeAttribute> authAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
                .Union(context.MethodInfo.GetCustomAttributes(true))
                .OfType<AuthorizeAttribute>();

            if (authAttributes.Any() && !operation.Responses.Any(r => r.Key == "401"))
                operation.Responses.Add("401", new OpenApiResponse { Description = "User not authenticated." });

            // if (authAttributes.Any() && !operation.Responses.Any(r => r.Key == "403"))
            //     operation.Responses.Add("403", new OpenApiResponse { Description = "User not authorized to access this endpoint." });
        }
    }
}

and set it in your Program.cs file (ASP.NET 6+):

builder.Services.AddSwaggerGen(c =>
{
    c.OperationFilter<AuthResponsesOperationFilter>();
};

or Startup.cs file (ASP.NET 5):

services.AddSwaggerGen(c =>
{
    c.OperationFilter<AuthResponsesOperationFilter>();
};

See here for more details: Swashbuckle Operation filters

Baccata
  • 473
  • 1
  • 7
  • 15
2

Could you please try with below attribute in the action method,

 [ProducesResponseType(typeof(ProblemDetails), (int)HttpStatusCode.Unauthorized)] 
Anupam Maiti
  • 225
  • 1
  • 2
  • 10
  • 1
    When I add that, I still get the above 401 under Server Response, but then under Responses, I see 401 Unauthorized. Without that attribute, I get 401 Undocumented under Server Response, and 200 Success under Responses. I will add screen shots in my original post. I also tested with Postman and with the original code, it does show 401 Unauthorized. It is the Swagger/Swashbuckle page that is not. – JoeD Apr 11 '20 at 16:30