J.Doe
J.Doe

Reputation: 1921

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

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
      }
    },

Upvotes: 183

Views: 289962

Answers (11)

Rasshme
Rasshme

Reputation: 1641

Below is the code for .NET SDK 8. To be able to provide bearer token in Swagger, below code is to be added to Program.cs. Add package Swashbuckle.AspNetCore.Filters, which is required for using SecurityRequirementsOperationFilter, which is used to add security requirements to your relevant API endpoints.

builder.Services.AddSwaggerGen(options =>
{
    options.AddSecurityDefinition("oauth2", new Microsoft.OpenApi.Models.OpenApiSecurityScheme()
    {
        In = Microsoft.OpenApi.Models.ParameterLocation.Header,
        Name = "Authorization",
        Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey
    });

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

A lock will start showing in Swagger as below enter image description here and when you click on it, below popup appears to enter token value.

enter image description here

Upvotes: 0

Ghostyshka
Ghostyshka

Reputation: 93

The following code works for me:

using Microsoft.AspNetCore.Authentication.JwtBearer;

builder.Services.AddSwaggerGen(options =>
{
    options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, new Microsoft.OpenApi.Models.OpenApiSecurityScheme
    {
        Name = "Authorization",
        Type = Microsoft.OpenApi.Models.SecuritySchemeType.Http,
        Scheme = JwtBearerDefaults.AuthenticationScheme,
        BearerFormat = "JWT",
        In = Microsoft.OpenApi.Models.ParameterLocation.Header,
        Description = "JWT Authorization header using the Bearer scheme."
    });
    options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement {
    {
            new Microsoft.OpenApi.Models.OpenApiSecurityScheme {
                    Reference = new Microsoft.OpenApi.Models.OpenApiReference {
                        Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme,
                            Id = JwtBearerDefaults.AuthenticationScheme
                    }
                },
                new string[] {}
    }
    });
});

Upvotes: 1

Ali Talebi
Ali Talebi

Reputation: 11

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

Upvotes: 1

Ozan Yasin Dogan
Ozan Yasin Dogan

Reputation: 360

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

Upvotes: 8

user2809176
user2809176

Reputation: 1275

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[] {}
                    }
                });
});

Upvotes: 21

Igor
Igor

Reputation: 4003

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.

Upvotes: 157

cdev
cdev

Reputation: 5361

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

Upvotes: 7

Jo&#227;o Ignacio
Jo&#227;o Ignacio

Reputation: 704

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

        });

Upvotes: 46

Alex
Alex

Reputation: 9720

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

Upvotes: 277

Vadym K
Vadym K

Reputation: 1665

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

Upvotes: 149

Pavel K.
Pavel K.

Reputation: 1073

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

Upvotes: 5

Related Questions