SwaggerUI с авторизацией токена-носителя .NetCore 3.0

Я пытаюсь добавить заголовок авторизации в тест SwaggerUI api. ниже мой Startup.cs

public void ConfigureServices(IServiceCollection services)
    {
       
        services.AddControllers();
        services.Configure<ApiBehaviorOptions>(options =>
        {
            options.SuppressModelStateInvalidFilter = true;
        });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo
            {
                Version = "v1",
                Title = "API",
                Description = "QPIN API with ASP.NET Core 3.0",
                Contact = new OpenApiContact()
                {
                    Name = "Tafsir Dadeh Zarrin",
                    Url = new Uri("http://www.tdz.co.ir")
                }
            });
            var securitySchema = new OpenApiSecurityScheme
            {
                Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
                Name = "Authorization",
                In = ParameterLocation.Header,
                Type = SecuritySchemeType.ApiKey
            };
            c.AddSecurityDefinition("Bearer", securitySchema);
            
            var securityRequirement = new OpenApiSecurityRequirement();
            securityRequirement.Add(securitySchema, new[] { "Bearer" });
            c.AddSecurityRequirement(securityRequirement);
            
        });
    }

    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider)
    {
        app.UseCors("Cors");


        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseMiddleware<ApiResponseMiddleware>();
        app.UseSwagger();
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
        });
        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();


        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });

    }

Кнопка авторизации была добавлена ​​в пользовательский интерфейс Swagger, и я ввел требуемый токен доступа, как показано ниже.

авторизовать swaggerUI

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

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


person VahiD    schedule 02.10.2019    source источник
comment
Было бы хорошо сказать, какую версию Swagger (Swashbuckle) вы используете. Вы получаете ошибку в консоли? Вы можете проверить эту проблему github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1197   -  person Julien Jacobs    schedule 02.10.2019
comment
это последняя версия (релиз condidate), которую я обновил через диспетчер пакетов в VS2019 (5.0.0. rc3). когда я выполняю API, я получаю сообщение об ошибке "неавторизовано", больше ничего в консоли   -  person VahiD    schedule 02.10.2019


Ответы (4)


Моя реализация - исключает блокировки на незащищенных конечных точках - с OperationFilter

internal static void SwaggerSetup(this IServiceCollection services, OpenApiInfo settings)
    {
        if (settings.Version != null)
        {
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc(settings.Version, settings);
                c.OperationFilter<AddAuthHeaderOperationFilter>();
                c.AddSecurityDefinition("bearer", new OpenApiSecurityScheme
                {
                    Description = "`Token only!!!` - without `Bearer_` prefix",
                    Type = SecuritySchemeType.Http,
                    BearerFormat = "JWT",
                    In = ParameterLocation.Header,
                    Scheme = "bearer"
                });
            });
        }
    }

и OperationFilter

private class AddAuthHeaderOperationFilter : IOperationFilter
    {
        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            var isAuthorized = (context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any()
                                && !context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType<AllowAnonymousAttribute>().Any()) //this excludes controllers with AllowAnonymous attribute in case base controller has Authorize attribute
                                || (context.MethodInfo.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any()
                                && !context.MethodInfo.GetCustomAttributes(true).OfType<AllowAnonymousAttribute>().Any()); // this excludes methods with AllowAnonymous attribute

            if (!isAuthorized) return;

            operation.Responses.TryAdd("401", new OpenApiResponse { Description = "Unauthorized" });
            operation.Responses.TryAdd("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] = new string []{} }
            };
        }
    }

Ссылка https://thecodebuzz.com/jwt-authorize-swagger-using-ioperationfilter-asp-net-core/

просто добавил условие для исключения AllowAnonymous декорированных методов

«Результат»

person Kiril Kolev    schedule 26.03.2020
comment
Обновлена ​​проверка isAuthorized, чтобы исключить контроллеры, украшенные атрибутом AllowAnnonymous (в случае, если базовый контроллер имеет атрибут Authorize). - person Kiril Kolev; 30.06.2020

В вашем коде есть два пункта:

  1. Для OpenApiSecurityRequirement в OpenApiSecurityRequirement необходимо установить OpenApiReference
  2. Необходимо указать Scheme с bearer

Вот рабочая демонстрация:

services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo
    {
        Version = "v1",
        Title = "API",
        Description = "QPIN API with ASP.NET Core 3.0",
        Contact = new OpenApiContact()
        {
            Name = "Tafsir Dadeh Zarrin",
            Url = new Uri("http://www.tdz.co.ir")
        }
    });
    var securitySchema = new OpenApiSecurityScheme
    {
        Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.Http,
        Scheme = "bearer",
        Reference = new OpenApiReference
        {
            Type = ReferenceType.SecurityScheme,
            Id = "Bearer"
        }
    };
    c.AddSecurityDefinition("Bearer", securitySchema);

    var securityRequirement = new OpenApiSecurityRequirement();
    securityRequirement.Add(securitySchema, new[] { "Bearer" });
    c.AddSecurityRequirement(securityRequirement);
});
person Edward    schedule 03.10.2019
comment
Блестящий ответ, спасибо. Мне было интересно, есть ли способ определить, какие API требуют авторизации, поэтому просто отправьте заголовок авторизации для этих API? - person VahiD; 03.10.2019
comment
Да, решение описано на гитхабе Swashbuckle.AspNetCore - person Bruno Martins; 21.02.2020

Обратите внимание, что после .Net Core 3.0 тип некоторых параметров был изменен следующим образом:

In = ParameterLocation.Header,

Тип = SecuritySchemeType.ApiKey

services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "My 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
            });
        });

Ссылка: https://ppolyzos.com/2017/10/30/add-jwt-bearer-authorization-to-swagger-and-asp-net-core/

person Hossein POURAKBAR    schedule 08.04.2020

В дополнение к тому, что сказал Кирил, в моем случае я хочу получить токен JWT через Swagger, и это код, который я использовал, добавив OpenApiSecurityScheme к тому, что он предложил:

c.AddSecurityDefinition("bearer",
                    new OpenApiSecurityScheme{
                        Flows = new OpenApiOAuthFlows()
                        {
                            ClientCredentials = new OpenApiOAuthFlow()
                            {
                                TokenUrl = new Uri("https://auth.myauthserver.com/oauth2/token"),
                                Scopes = new Dictionary<string, string>(){ {"myscope", "Access API"}},
                                AuthorizationUrl = new Uri("https://auth.myauthserver.com/oauth2/authorize")
                            }
                        }, 
                        Type = SecuritySchemeType.OAuth2,
                        OpenIdConnectUrl = new Uri("https://myauthserver/.well-known/openid-configuration"),
                        BearerFormat = "JWT",
                        In = ParameterLocation.Header,
                        Scheme = "bearer"
                    });
person Alessio Di Salvo    schedule 26.05.2020