36

I am developing some Web API with .NET Core 3.0 and want to integrate it with SwashBuckle.Swagger. It is working fine, but when I add JWT authentication, it does not work as I expect. To do that, I added the code below:

services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "My Web API", Version = "v1" });
        c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
        {
            Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
            Name = "Authorization",
            In = ParameterLocation.Header,
            Type = SecuritySchemeType.ApiKey
        });
    });

After adding AddSecurityDefinition function, I can see the Authorize button and when I click it, I see the form below: enter image description here

Then I type Bearer WhatEverApiKeyIsfgdgdgdg845734987fgdhgiher635kjh. After doing it, I expect to see authorization: Bearer WhatEverApiKeyIsfgdgdgdg845734987fgdhgiher635kjh in the request's header when I send a request to the Web API from Swagger, but authorization is not added to the request header. I am using SwashBuckle.Swagger(5.0.0-rc3). Please note there are many samples which work fine on .NET Core 2.0, but Swashbuckle swagger functions has changed on the latest version so I cannot use those samples.

Pang
  • 8,605
  • 144
  • 77
  • 113
Mehrdad Babaki
  • 7,301
  • 12
  • 39
  • 59
  • Possible duplicate of [Authorization for JWT bearer in Swashbuckle .NET Core 2](https://stackoverflow.com/questions/48985240/authorization-for-jwt-bearer-in-swashbuckle-net-core-2) – Helen Oct 01 '19 at 08:04
  • 4
    On the link you mentioned there is no answer. Also .net core 3.0 is slightly different. – Mehrdad Babaki Oct 01 '19 at 08:24
  • The answer is to add `.AddSecurityRequirement` (globally) or `.Security` (on the operation level) - as explained in the answers to the linked question. `AddSecurityDefinition` alone is not enough. – Helen Oct 01 '19 at 08:58
  • I added but nothing changed. I think that's why it is not selected as answer. – Mehrdad Babaki Oct 01 '19 at 09:28
  • I answered this recently on another question have a look here: https://stackoverflow.com/a/57872872/3952573 – Pavlos Oct 03 '19 at 12:47

6 Answers6

88

After some research, I eventually found the answer here

Before seeing this page, I knew that I should use AddSecurityRequirement after AddSecurityDefinition because of many samples, but it was a problem that the function parameters have changed on .NET Core 3.0.

By the way, the final answer is as below:

services.AddSwaggerGen(c =>
{
  c.SwaggerDoc("v1", new OpenApiInfo { 
    Title = "My API", 
    Version = "v1" 
  });
  c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme {
    In = ParameterLocation.Header, 
    Description = "Please insert JWT with Bearer into field",
    Name = "Authorization",
    Type = SecuritySchemeType.ApiKey 
  });
  c.AddSecurityRequirement(new OpenApiSecurityRequirement {
   { 
     new OpenApiSecurityScheme 
     { 
       Reference = new OpenApiReference 
       { 
         Type = ReferenceType.SecurityScheme,
         Id = "Bearer" 
       } 
      },
      new string[] { } 
    } 
  });
});
Jesse
  • 3,093
  • 6
  • 22
  • 35
Mehrdad Babaki
  • 7,301
  • 12
  • 39
  • 59
  • 11
    This worked.. Tip : don't forget to write "Bearer " before the actual token. And it's a bit annoying that swagger always says authorized, no matter what you write in the Textbox... Thanks! – CodeHacker Nov 08 '19 at 16:23
  • 1
    Whoever Saves a Life Saves the World. You saved my life ;-) thx – Vahid Farahmandian Mar 02 '20 at 12:12
20

If you are using Swagger 3.0 then it has build-in support for JWT authentication.

You need to use ParameterLocation.Header, SecuritySchemeType.Http, bearer, and JWT in OpenApiSecurityScheme as shown below.

After this, you wouldn't need to specify token in Bearer {token} format. Only specify the token and the security scheme will automatically apply it in the header.

// Bearer token authentication
OpenApiSecurityScheme securityDefinition = new OpenApiSecurityScheme()
{
    Name = "Bearer",
    BearerFormat = "JWT",
    Scheme = "bearer",
    Description = "Specify the authorization token.",
    In = ParameterLocation.Header,
    Type = SecuritySchemeType.Http,
};
c.AddSecurityDefinition("jwt_auth", securityDefinition);

// Make sure swagger UI requires a Bearer token specified
OpenApiSecurityScheme securityScheme = new OpenApiSecurityScheme()
{
    Reference = new OpenApiReference()
    {
        Id = "jwt_auth",
        Type = ReferenceType.SecurityScheme
    }
};
OpenApiSecurityRequirement securityRequirements = new OpenApiSecurityRequirement()
{
    {securityScheme, new string[] { }},
};
c.AddSecurityRequirement(securityRequirements);

enter image description here

Jon Bates
  • 2,821
  • 2
  • 26
  • 41
ameya
  • 976
  • 9
  • 17
9

In the accepted answer, "Bearer " is required to be written before the actual token. A similar approach in which typing "Bearer " can be skipped is the following:

c.SwaggerDoc("v1", new OpenApiInfo { Title = "Example API", Version = "v1" });

c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
    Type = SecuritySchemeType.Http,
    BearerFormat = "JWT",
    In = ParameterLocation.Header,
    Scheme = "bearer",
    Description = "Please insert JWT token into field"
});

c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
    {
        new OpenApiSecurityScheme
        {
            Reference = new OpenApiReference
            {
                Type = ReferenceType.SecurityScheme,
                Id = "Bearer"
            }
        },
        new string[] { }
    }
});

Here, only pasting the JWT token is required for this to work.

Pang
  • 8,605
  • 144
  • 77
  • 113
diver
  • 212
  • 1
  • 3
  • 10
8

Here's a solution updated for Swashbuckle.AspNetCore 5.3.2, integrated with IdentityServer4, with an API secured using a Bearer token.

In ConfigureServices() method:

services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
    options.AddSecurityDefinition("Bearer", SecuritySchemes.BearerScheme(Configuration));
    options.AddSecurityRequirement(new OpenApiSecurityRequirement()
    {
        { SecuritySchemes.OAuthScheme, new List<string>() }
    });
});

In Configure() method:

        app.UseSwaggerUI(options =>
        {
            options.SwaggerEndpoint("/My.Api/swagger/v1/swagger.json", "My API V1");
            options.OAuthClientId(Clients.TestClient);
            options.OAuthAppName("My Api - Swagger");
            options.OAuthClientSecret(Configuration["TestClientSecret"]);
        });

internal static class SecuritySchemes
{
    public static OpenApiSecurityScheme BearerScheme(IConfiguration config) => new OpenApiSecurityScheme
    {
        Type = SecuritySchemeType.OAuth2,
        Description = "Standard authorisation using the Bearer scheme. Example: \"bearer {token}\"",
        In = ParameterLocation.Header,
        Name = "Authorization",
        Scheme = "Bearer",
        OpenIdConnectUrl = new System.Uri($"{config["TokenServerUrl"]}.well-known/openid-configuration"),
        BearerFormat = "JWT",
        Flows = new OpenApiOAuthFlows
        {
            Password = new OpenApiOAuthFlow
            {
                AuthorizationUrl = new System.Uri($"{config["TokenServerUrl"]}connect/authorize"),
                Scopes = new Dictionary<string, string>
                    {
                        { Scopes.Api, "My Api" }
                    },
                TokenUrl = new System.Uri($"{config["TokenServerUrl"]}connect/token")
            }
        }
    };

    public static OpenApiSecurityScheme OAuthScheme => new OpenApiSecurityScheme
    {
        Reference = new OpenApiReference
        {
            Type = ReferenceType.SecurityScheme,
            Id = "Bearer"
        },
        Scheme = "oauth2",
        Name = "Bearer",
        In = ParameterLocation.Header,

    };
}
Pang
  • 8,605
  • 144
  • 77
  • 113
Paul Taylor
  • 5,183
  • 4
  • 39
  • 62
  • 1
    This is a life saver. It also works for implicit flow where I changed Password to Implicit in the Flows setup. Thank you so very much! – Larsbj Apr 22 '20 at 20:20
  • 2
    OK, this is the only example that worked for me. I can't believe how difficult they make this. – The Muffin Man Apr 18 '21 at 06:05
3

If you don't want to add a token manually and you want the scopes to be selectable along with passing a clientId to the identity server you can add something like this.

I have used implicit flow, but you can configure any flow using the following mechanism:

options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme()
{
  Flows = new OpenApiOAuthFlows
  {
    Implicit = new OpenApiOAuthFlow
    {                            
      AuthorizationUrl = new Uri("http://localhost"),
      TokenUrl = new Uri("http://localhost"),
      Scopes = new Dictionary<string, string>
      {
        { "Foundation API", "FoundationApi" }
      }
    }
  },
  In = ParameterLocation.Header,                    
  Name = "Authorization",
  Type = SecuritySchemeType.OAuth2                    
});

The output will be like this:

enter image description here

Jesse
  • 3,093
  • 6
  • 22
  • 35
3

If anyone is using NSwag and has landed here after searching the solution, here is the link from the official documentation.

NSwag Enable JWT authentication

PS: I know the original question was for SwashBuckle, but Google shows this link first when searching for NSwag as well.