Swashbuckle Swagger UI padlocks com OAS3 [duplicado]

Nov 25 2020

Eu tenho um ASP.Net Core Rest Web API documentado com a geração Swagger do Swashbuckles (.net v5 e Swashbuckle.AspNetCore v5.6.3). Ele gera documentação Swagger e UI com suporte OAS3.

Além disso, minha API usa tokens de portador JWT. Então, adicionei este código à configuração swagger:

options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
    In = ParameterLocation.Header,
    Name = "Authorization",
    Type = SecuritySchemeType.ApiKey,
    Description = "Put `bearer` keyword in front of token"
});

options.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
    {
        new OpenApiSecurityScheme()
        {
            Reference = new OpenApiReference()
            {
                Id = "Bearer",
                Type = ReferenceType.SecurityScheme
            }
        },
        Array.Empty<string>()
    }
});

E como esperado, ele adicionou o recurso de autorização à IU do Swagger:

Mas também notei alguns cadeados ao lado de cada solicitação HTTP. Eles são desbloqueados antes da autorização:

E após a autorização eles bloqueiam:

Como posso fazer com que esses cadeados sinalizem se a autorização é necessária ou não (acho que já vi os mesmos cadeados em algum lugar fazendo isso e parece bastante natural para eles fazerem esse tipo de coisa também)?

Já tentei algo parecido, mas não funcionou (os cabeçalhos de solicitação não continham mais o token jwt):

options.OperationFilter<SecurityRequirementsOperationFilter>();

Eu descobri que o problema é que meu Swagger está usando OAS3 e SecurityRequirementsOperationFilterdependendo do OAS2. Tentei procurar alternativas, mas parece que não existem ferramentas semelhantes para OAS3.

O que devo fazer? Devo esquecer esse recurso? Mas esse parece ser o único propósito dessas travas. Há alguma maneira de ter esse recurso e permanecer com o OAS3 (também não tenho certeza se realmente preciso tanto do suporte do OAS3).

Respostas

catman0745 Nov 25 2020 at 13:38

Depois de alguma pesquisa, encontrei a resposta aqui: https://stackoverflow.com/a/61365691/13851956.

Portanto, o código é:

options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
    Description = "No need to put the `bearer` keyword in front of token",
    Type = SecuritySchemeType.Http,
    Scheme = "bearer",
    BearerFormat = "JWT"
});
options.OperationFilter<AuthorizationOperationFilter>();
public class AuthorizationOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var actionMetadata = context.ApiDescription.ActionDescriptor.EndpointMetadata;
        var isAuthorized = actionMetadata.Any(metadataItem => metadataItem is AuthorizeAttribute);
        var allowAnonymous = actionMetadata.Any(metadataItem => metadataItem is AllowAnonymousAttribute);
        if (!isAuthorized || allowAnonymous)
        {
            return;
        }
        
        operation.Parameters ??= new List<OpenApiParameter>();
        operation.Security = new List<OpenApiSecurityRequirement>
        {
            new OpenApiSecurityRequirement
            {
                {
                    new OpenApiSecurityScheme
                    {
                        Reference = new OpenApiReference
                        {
                            Id = "Bearer",
                            Type = ReferenceType.SecurityScheme
                        }
                    },
                    Array.Empty<string>()
                }
            }
        };
    }
}

O resultado é que os cadeados aparecem apenas ao lado das ações marcadas com [Autorizar] e não marcadas com atributos [PermitirAnônimo]: