Candados Swashbuckle Swagger UI con OAS3 [duplicado]

Nov 25 2020

Tengo una API web ASP.Net Core Rest documentada con la generación Swagger de Swashbuckles (.net v5 y Swashbuckle.AspNetCore v5.6.3). Genera documentación y UI de Swagger con soporte OAS3.

Además, mi API usa tokens de portador JWT. Entonces, agregué este código a la configuración de 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>()
    }
});

Y como se esperaba, agregó la capacidad de autorización a la interfaz de usuario de Swagger:

Pero también noté algunos candados junto a cada solicitud HTTP. Se desbloquean antes de la autorización:

Y después de la autorización bloquean:

¿Cómo puedo hacer que estos candados indiquen si se requiere autorización o no (creo que he visto los mismos candados en alguna parte haciendo esto y les parece bastante natural hacer este tipo de cosas también)?

Ya intenté algo así, pero no funcionó (los encabezados de solicitud ya no contenían el token jwt):

options.OperationFilter<SecurityRequirementsOperationFilter>();

Me di cuenta de que el problema es que mi Swagger usa OAS3 y SecurityRequirementsOperationFilterdepende de OAS2. Intenté buscar alternativas, pero parece que no hay herramientas similares para OAS3.

¿Qué tengo que hacer? ¿Debo olvidar esta función? Pero ese parece el único propósito de estos candados. ¿Hay alguna forma de tener esta función y permanecer con OAS3 (tampoco estoy seguro de si realmente necesito tanto soporte de OAS3)?

Respuestas

catman0745 Nov 25 2020 at 13:38

Después de investigar un poco, encontré la respuesta aquí: https://stackoverflow.com/a/61365691/13851956.

Entonces el código es:

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

El resultado es que los candados aparecen solo junto a las acciones marcadas con [Autorizar] y no marcadas con los atributos [AllowAnonymous]: