Setting up Swagger (ASP.NET Core) using the Authorization headers (Bearer)
Asked Answered
T

9

173

I have a Web API (ASP.NET Core) and I am trying to adjust the swagger to make the calls from it. The calls must contains the Authorization header and I am using Bearer authentication. The calls from third party apps like Postman, etc. go fine. But I am having the issue with setting up the headers for swagger (for some reason I don't receive the headers). This is how it looks like now:

  "host": "localhost:50352",
  "basePath": "/" ,
  "schemes": [
    "http",
    "https"
  ],
 "securityDefinitions":  {
    "Bearer": {
      "name": "Authorization",
      "in": "header",
      "type": "apiKey",
      "description": "HTTP/HTTPS Bearer"
    }
  },
  "paths": { 
    "/v1/{subAccountId}/test1": {
      "post": {
        "tags": [
          "auth"
        ],
        "operationId": "op1",
        "consumes": ["application/json", "application/html"],
        "produces": ["application/json", "application/html"],
        "parameters": [
          {
            "name": "subAccountId",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "security":[{
          "Bearer": []
        }],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "BadRequest",
            "schema": {
              "$ref": "#/definitions/ErrorResponse"
            }
          },
          "401": {
            "description": "Unauthorized",
            "schema": {
              "$ref": "#/definitions/ErrorResponse"
            }
          },
          "500": {
            "description": "InternalServerError",
            "schema": {
              "$ref": "#/definitions/ErrorResponse"
            }
          }
        },
        "deprecated": false
      }
    },
Therewithal answered 17/4, 2017 at 8:11 Comment(1)
I did it with firebase #61541206Openwork
H
264

ApiKeyScheme was deprecated, in version 5 you can use like this:

services.AddSwaggerGen(c =>
  {
    c.SwaggerDoc("v1", new Info { Title = "You api title", Version = "v1" });
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
      {
        Description = @"JWT Authorization header using the Bearer scheme. \r\n\r\n 
                      Enter 'Bearer' [space] and then your token in the text input below.
                      \r\n\r\nExample: 'Bearer 12345abcdef'",
         Name = "Authorization",
         In = ParameterLocation.Header,
         Type = SecuritySchemeType.ApiKey,
         Scheme = "Bearer"
       });

    c.AddSecurityRequirement(new OpenApiSecurityRequirement()
      {
        {
          new OpenApiSecurityScheme
          {
            Reference = new OpenApiReference
              {
                Type = ReferenceType.SecurityScheme,
                Id = "Bearer"
              },
              Scheme = "oauth2",
              Name = "Bearer",
              In = ParameterLocation.Header,

            },
            new List<string>()
          }
        });
    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
    c.IncludeXmlComments(xmlPath);
});
Hakenkreuz answered 21/11, 2019 at 10:32 Comment(8)
Can confirm this is working like a charm for .NET Core 3.0 - the code I wrote when using .NET Core 2.2 no longer worked after the upgrade and this is what I neededSash
Minor points: i) I needed to use <BR/> instead of \r\n for the message to display correctly. ii) instead of new Info { ... I needed new OpenApiInfo {Title ... . [using swashbuckle.aspnetcore 5.0.0 and Microsoft.OpenApi 1.1.4 [.net core 3.1]]Tayler
What about: 1. AllowAnonymous 2. Roles?Degas
This works for me but the description "\r\n" part is not working...Apps
The combination of SecuritySchemeType.ApiKey & Scheme="Bearer" seems to not provide any scheme value in the parameter of the Authorization header. Any scheme value used with SecuritySchemeType.ApiKey results in a header with a format of {"Authorization","value"}. If {"Authorization","scheme value"} is desired, then SecuritySchemeType.Http & Scheme="Bearer" should be used.Maurey
@Apps It gets turned into HTML so you can use <br/> instead of "\r\n"Mutinous
Works with .net 6 too.Tila
I using .net 7 and still workedCleistogamy
R
149

First of all, you can use Swashbuckle.AspNetCore nuget package for auto generating your swagger definition. (tested on 2.3.0)

After you've installed package, setup it in Startup.cs in method ConfigureServices

services.AddSwaggerGen(c => {
    c.SwaggerDoc("v1", new Info { Title = "You api title", Version = "v1" });
    c.AddSecurityDefinition("Bearer",
        new ApiKeyScheme { In = "header",
          Description = "Please enter into field the word 'Bearer' following by space and JWT", 
          Name = "Authorization", Type = "apiKey" });
    c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>> {
        { "Bearer", Enumerable.Empty<string>() },
    });

});

Then you can use Authorize button at the top right of the page.

At least you can try to use this package to generate valid swagger definition

Rashad answered 17/4, 2017 at 8:46 Comment(8)
Good answer but when I do that with ABP boilerplate, it doesn't work with Dynamic Web Api (aspnetboilerplate.com/Pages/Documents/Dynamic-Web-API)Leena
@VadimK That worked perfectly until I upgraded to .NET Core 2.0Rootlet
In the case this helps, in the Auth box , in the value input you have to put exactly the Auth header not only the JWT (in the case you are using it). This means : Bearer your_token_jwtRhodian
Make sure you prefix you token with "Bearer". I was not using Bearer your_token_jwtWalkthrough
And what they did for: 1. AllowAnonymous 2. Roles?Degas
i would like to skip that bearer prefix. .how to programmatically catch the token value and prepend it with bearer in case its missing?Lowney
What is ApiKeyScheme ?Wei
This is working at .net 5. For ApiKeyScheme I do not know what is it? I use "Bearer" for that lost enumeration class.Wei
A
143

TIP!

To avoid always write the keyword Bearer on the Swagger(a.k.a Swashbuckle) auth dialog, like: "bearer xT1...", you can use the code/config below on ConfigureServices(...) method at your Startup class:

using Microsoft.OpenApi.Models;
...


services.AddSwaggerGen(setup =>
{
    // Include 'SecurityScheme' to use JWT Authentication
    var jwtSecurityScheme = new OpenApiSecurityScheme
    {
        BearerFormat = "JWT",
        Name = "JWT Authentication",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.Http,
        Scheme = JwtBearerDefaults.AuthenticationScheme,
        Description = "Put **_ONLY_** your JWT Bearer token on textbox below!",

        Reference = new OpenApiReference
        {
            Id = JwtBearerDefaults.AuthenticationScheme,
            Type = ReferenceType.SecurityScheme
        }
    };

    setup.AddSecurityDefinition(jwtSecurityScheme.Reference.Id, jwtSecurityScheme);

    setup.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        { jwtSecurityScheme, Array.Empty<string>() }
    });

});

We can make this, only by changing the Type property of the OpenApiSecurityScheme class to:

Type = SecuritySchemeType.Http

instead

Type = SecuritySchemeType.ApiKey.

:)

Like this...

Packages:

Swashbuckle.AspNetCore(5.6.3)
Swashbuckle.AspNetCore.SwaggerUI(5.6.3)

I'am using .NET Core 3.1.

Antiperiodic answered 18/11, 2020 at 19:9 Comment(5)
Many Thanks for posting the tip. I was looking for a way to avoid typing bearer in swagger and this helped.Headland
Thanks! This worked for me & displayed the authorize button in Swagger UI.Corwun
Thanks, worked. Nice and easyPhotomural
what is JwtBearerDefaults?Wei
@Wei learn.microsoft.com/en-us/dotnet/api/…Antiperiodic
H
45

Using ASP.Net Core 3.1, here's what worked for me:

services.AddSwaggerGen(s =>
        {
            s.SwaggerDoc("v1", new OpenApiInfo
            {
                Version = "v1",
                Title = "Chat API",
                Description = "Chat API Swagger Surface",
                Contact = new OpenApiContact
                {
                    Name = "João Victor Ignacio",
                    Email = "[email protected]",
                    Url = new Uri("https://www.linkedin.com/in/ignaciojv/")
                },
                License = new OpenApiLicense
                {
                    Name = "MIT",
                    Url = new Uri("https://github.com/ignaciojvig/ChatAPI/blob/master/LICENSE")
                }

            });

            s.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
            {
                Description = "JWT Authorization header using the Bearer scheme (Example: 'Bearer 12345abcdef')",
                Name = "Authorization",
                In = ParameterLocation.Header,
                Type = SecuritySchemeType.ApiKey,
                Scheme = "Bearer"
            });

            s.AddSecurityRequirement(new OpenApiSecurityRequirement
            {
                {
                    new OpenApiSecurityScheme
                    {
                        Reference = new OpenApiReference
                        {
                            Type = ReferenceType.SecurityScheme,
                            Id = "Bearer"
                        }
                    },
                    Array.Empty<string>()
                }
            });

        });
Henpeck answered 12/7, 2020 at 17:43 Comment(0)
C
19

Update 17.12.2022

in case someone has problems adding JWT to .Net 7,8 the next code worked for me, should work in .Net 6 as well

builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "Test01", Version = "v1" });

    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
    {
        Name = "Authorization",
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer",
        BearerFormat = "JWT",
        In = ParameterLocation.Header,
        Description = "JWT Authorization header using the Bearer scheme."

    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                          new OpenApiSecurityScheme
                          {
                              Reference = new OpenApiReference
                              {
                                  Type = ReferenceType.SecurityScheme,
                                  Id = "Bearer"
                              }
                          },
                         new string[] {}
                    }
                });
});
C answered 17/12, 2022 at 14:1 Comment(6)
Ty good sir. My only recommendation is to change the "Bearer" for JwtBearerDefaults.AuthenticationScheme, which is the same, but fancier.Kenelm
Could you clarify why it is better? In my solution there is no JwtBearerDefaults, so in that case i need to install some package. Does it worth it?C
Using the JwtBearerDefaults is not "better" in any way friend...I just find its more elegant. Besides, using defined constants prevents typo errors...For me its a good practice.Kenelm
yes, it is better to avoid magic strings, agree)C
thanks, work well for me and if someone have problem with that you should pass header of Authorization that should look like "bearer [accessTokenValue]", for example in react: config.headers['Authorization'] = Bearer ${auth?.accessToken};Gavrielle
I confirm this works on dotnet 8Falconiform
A
7

There is no need to generate token separate and key in swagger. Swagger support generation part too. Below work for me with asp.net core 3.1 and keycloack auth.

swagger.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, new OpenApiSecurityScheme
{
    Type = SecuritySchemeType.OAuth2,
    Flows = new OpenApiOAuthFlows
    {
        Implicit = new OpenApiOAuthFlow
        {
            AuthorizationUrl = new Uri("https://youauthsrv.com/auth/realms/your-realm/protocol/openid-connect/auth"),
        }
    },
    In = ParameterLocation.Header,
    Scheme = JwtBearerDefaults.AuthenticationScheme,
});

swagger.AddSecurityRequirement(new OpenApiSecurityRequirement
{
    {
        new OpenApiSecurityScheme
        {
            Reference = new OpenApiReference
            {
                Type = ReferenceType.SecurityScheme,
                Id = JwtBearerDefaults.AuthenticationScheme
            }
        },
        new string[] {}
    }
});

in Configure

app.UseSwaggerUI(c =>
{
    c.OAuthClientId("clientname");
    c.OAuthRealm("your-realm");
});
Amberlyamberoid answered 22/2, 2021 at 7:15 Comment(0)
H
5

Currently Swagger has functionality for authentication with JWT-token and can automatically add token into header, I have answered here.

Higdon answered 8/12, 2017 at 12:1 Comment(0)
R
2

Tested on .Net 8, Dec 2023. with [Authorize] attribute

I have tried other answers and had to come up with my own solution because other answers were making all my api endpoints looking like they were all needed authentication with padlocks around no matter some does not require authentication actually. So above solutions were dealing with it globally, applying to every endpoint which is not correct and the produced swagger.json/yaml file was also faulty for the same reason which could affect service client generations in other platforms. That's why I felt the need to post this here.

I only wanted where I specifically put [Authorize] attribute to be authorized basically so, during service registration in a typical web application, you can add this:

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new OpenApiInfo { Title = "JadeWebAPI", Version = "v1" });

    options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Name = "Authorization",
        Description = "JWT token must be provided",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.Http,
        Scheme = JwtBearerDefaults.AuthenticationScheme
    });

    //options.AddSecurityRequirement(new OpenApiSecurityRequirement
    //{
    //    {
    //        new OpenApiSecurityScheme
    //        {
    //            Name = "Bearer",
    //            In = ParameterLocation.Header,
    //            Reference = new OpenApiReference
    //            {
    //                Id="Bearer",
    //                Type=ReferenceType.SecurityScheme,
    //            }
    //        },
    //        new string[]{ }
    //    }
    //});

    options.OperationFilter<AuthorizeCheckOperationFilter>();
});

So you will notice that I added and commented AddSecurityRequirement section to not globally affect all endpoints but added instead an OperationFilter to configuration options in the end. This is the implementation of IOperationFilter for this:

public class AuthorizeCheckOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        if (context.MethodInfo.DeclaringType is null)
            return;

        var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any()
                    || context.MethodInfo.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any();

        if (hasAuthorize)
        {
            operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
            // operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" });

            var jwtBearerScheme = new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                }
            };

            operation.Security = new List<OpenApiSecurityRequirement>
            {
                new OpenApiSecurityRequirement
                {
                    [jwtBearerScheme] = Array.Empty<string>()
                }
            };
        }
    }
}

I think the code is self explanatory. I have also attached screenshots when using global/filter options. This gave a more refined solution to me and correct swagger.json/yaml output. No padlocks applied by swagger with my solution to the endpoints where [Authorize] attribute not applied

Padlocks applied everywhere no matter if the endpoint has [Authorize] attribute or not

Readiness answered 9/12, 2023 at 2:8 Comment(2)
This is a great addition to the previous answers! I ran into this answer that provides a default way to achieve the same, without a custom OperationFilter: https://mcmap.net/q/144641/-in-swagger-ui-how-can-i-remove-the-padlock-icon-from-quot-anonymous-quot-methodsLandscapist
@MiguelRebocho exactly, but it's plus minus doing the same thing like in the custom filter, you can check the source file here: github.com/mattfrear/Swashbuckle.AspNetCore.Filters/blob/master/…Readiness
R
0

The following code works for me:

services.AddSwaggerGen(config =>
{
    config.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Type = SecuritySchemeType.Http,
        In = ParameterLocation.Header,
        Scheme = "Bearer",
        BearerFormat = "JWT",
        Description = "JWT Authorization header using the Bearer scheme."
    });

    config.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                },
                In = ParameterLocation.Header,
            },
            new List<string>()
        }
    });
});
Rebecarebecca answered 16/9, 2023 at 12:5 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Reverie

© 2022 - 2024 — McMap. All rights reserved.