JWT Authentication and Swagger with .NET Core 3.0
Asked Answered
D

7

72

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.

Dedededen answered 1/10, 2019 at 6:31 Comment(5)
Possible duplicate of Authorization for JWT bearer in Swashbuckle .NET Core 2Birth
On the link you mentioned there is no answer. Also .net core 3.0 is slightly different.Dedededen
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.Birth
I added but nothing changed. I think that's why it is not selected as answer.Dedededen
I answered this recently on another question have a look here: https://mcmap.net/q/215918/-bearer-authentication-in-swagger-ui-when-migrating-to-swashbuckle-aspnetcore-version-5Thermomagnetic
D
150

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[] { } 
    } 
  });
});
Dedededen answered 1/10, 2019 at 11:27 Comment(5)
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!Idiotic
Code presented here does not need to type Bearer before token: thecodebuzz.com/…Scharf
Without c.swaggerDoc(..), it works like charm on .NET core 5.0/6.0 with swashbuckle! Thank you for sharing!Tega
Thanks, it works for me too. But need to add "Bearer" + JWT Token to that text boxJackboot
@Nick-Mehrdad-Babaki if endpoint return special json what we should to do? see this please #78428104Measurement
D
40

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

Delisadelisle answered 2/11, 2019 at 2:14 Comment(1)
Thank you! After many posts that did not work for me, this method did!!Jose
S
24

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.

Sluice answered 18/6, 2020 at 12:18 Comment(0)
J
14

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,

    };
}
Jawbone answered 20/4, 2020 at 14:49 Comment(2)
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!Cimex
OK, this is the only example that worked for me. I can't believe how difficult they make this.Addition
T
4

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

Tychonn answered 23/10, 2019 at 1:23 Comment(0)
F
4

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.

Fucoid answered 30/3, 2020 at 2:24 Comment(0)
S
0

In Accept answer you have to manually append "bearer" with token, this will create new issues, Swagger can append "bearer" with token watch this following link

JWT Authentication and Swagger with .NET Core 3 and 5 YouTube video

Simultaneous answered 20/8, 2021 at 7:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.