Аутентификация JWT и Swagger с .NET Core 3.0

Я разрабатываю веб-API с .NET Core 3.0 и хочу интегрировать его с SwashBuckle.Swagger. Он работает нормально, но когда я добавляю аутентификацию JWT, он работает не так, как я ожидал. Для этого я добавил код ниже:

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

После добавления функции AddSecurityDefinition я вижу кнопку «Авторизовать», а когда я нажимаю на нее, я вижу форму ниже: введите описание изображения здесь

Затем я набираю Bearer WhatEverApiKeyIsfgdgdgdg845734987fgdhgiher635kjh. После этого я ожидаю увидеть authorization: Bearer WhatEverApiKeyIsfgdgdgdg845734987fgdhgiher635kjh в заголовке запроса, когда я отправляю запрос к веб-API из Swagger, но авторизация не добавляется в заголовок запроса. Я использую SwashBuckle.Swagger (5.0.0-rc3). Обратите внимание, что есть много примеров, которые отлично работают в .NET Core 2.0, но функции Swagger Swagger в последней версии изменились, поэтому я не могу использовать эти образцы.


person Mehrdad Babaki    schedule 01.10.2019    source источник


Ответы (6)


После некоторого исследования я в конце концов нашел ответ здесь

Прежде чем увидеть эту страницу, я знал, что мне следует использовать AddSecurityRequirement после AddSecurityDefinition из-за множества примеров, но это была проблема, потому что параметры функции изменились в .NET Core 3.0.

Кстати, окончательный ответ такой:

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[] { } 
    } 
  });
});
person Mehrdad Babaki    schedule 01.10.2019
comment
Это сработало .. Совет: не забудьте написать Bearer перед фактическим токеном. И немного раздражает, что чванство всегда говорит авторизовано, что бы вы ни писали в текстовом поле ... Спасибо! - person CodeHacker; 08.11.2019
comment
Кто спасает жизнь, спасает мир. Ты спас мне жизнь ;-) thx - person Vahid Farahmandian; 02.03.2020

Если вы используете Swagger 3.0, он имеет встроенную поддержку аутентификации JWT.

Вам необходимо использовать ParameterLocation.Header, SecuritySchemeType.Http, bearer и JWT в OpenApiSecurityScheme, как показано ниже.

После этого вам не нужно указывать токен в формате Bearer {token}. Укажите только токен, и схема безопасности автоматически применит его в заголовке.

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

введите описание изображения здесь

person ameya    schedule 02.11.2019
comment
Спасибо! После многих сообщений, которые у меня не сработали, этот метод сработал !! - person Matt Casto; 28.03.2020

В принятом ответе необходимо указать Bearer перед фактическим токеном. Аналогичный подход, при котором ввод Bearer можно пропустить, заключается в следующем:

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

Здесь для работы требуется только вставка токена JWT.

person diver    schedule 18.06.2020
comment
У меня это работает, спасибо! - person Lari; 12.06.2021

Вот обновленное решение для Swashbuckle.AspNetCore 5.3.2, интегрированное с IdentityServer4, с API, защищенным с помощью токена-носителя.

В ConfigureServices() методе:

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

В Configure() методе:

        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,

    };
}
person Paul Taylor    schedule 20.04.2020
comment
Это спасатель жизни. Это также работает для неявного потока, когда я изменил пароль на неявный в настройке потоков. Огромное спасибо! - person Larsbj; 22.04.2020
comment
Хорошо, это единственный пример, который у меня сработал. Не могу поверить, насколько сложно они это делают. - person The Muffin Man; 18.04.2021

Если вы не хотите добавлять токен вручную и хотите, чтобы области можно было выбирать вместе с передачей clientId на сервер идентификации, вы можете добавить что-то вроде этого.

Я использовал неявный поток, но вы можете настроить любой поток, используя следующий механизм:

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

Результат будет таким:

введите здесь описание изображения

person Prabhanjan Kumar Mahapatra    schedule 23.10.2019

Если кто-то использует NSwag и попал сюда после поиска решения, вот ссылка из официальной документации.

NSwag Включить аутентификацию JWT

PS: Я знаю, что исходный вопрос был о SwashBuckle, но Google также показывает эту ссылку первой при поиске NSwag.

person Prateek Kumar Dalbehera    schedule 30.03.2020