Home > other >  Is there a way to document how an endpoint is protected using swaggerUI?
Is there a way to document how an endpoint is protected using swaggerUI?

Time:01-27

Heyho! I have a quite big application with some endpoints and authorization schemes. To protect them i created 3 AuthorizeAttributes for rights, rights in a different tenant and parameters, to check them before accessing the endpoint itself. and there are even more. Also i created authorization policies e.g. that the user needs to be listed in the requested users properties.

Now it would be really helpful for testing, documenting and developing if our swagger UI could list those attributes and policies that apply for the endpoint. is there any way to do this?

As a Framework i'M using microsoft MVC, so controllers all inherit from Microsoft.AspNetCore.Mvc.ControllerBase

as for the swagger package I'm using: Swashbuckle.AspNetCore.Swagger version 6.3.1. (SwaggerGen/SwaggerUi)

CodePudding user response:

Assuming ASP.NET Core and Swashbuckle, you can use a MarkupFilter to provide additional information in the Swagger UI:

using System;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;
using Microsoft.AspNetCore.Authorization;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace Tool
{
    internal class AuthorizationMarkupFilter : IOperationFilter
    {
        private static ImmutableHashSet<string> GetPolicies(MethodInfo methodInfo)
        {
            var actionAttributes = methodInfo.GetCustomAttributes<AuthorizeAttribute>(true);
            var controllerAttributes = methodInfo.DeclaringType.GetTypeInfo().GetCustomAttributes<AuthorizeAttribute>(true);

            var result = ImmutableHashSet<string>.Empty;

            foreach (var attribute in actionAttributes.Union(controllerAttributes))
            {
                if (!string.IsNullOrWhiteSpace(attribute.Policy))
                {
                    result = result.Add(attribute.Policy);
                }
            }

            return result;
        }

        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            var policies = GetPolicies(context.MethodInfo);

            if (policies.Count > 0)
            {
                var sb = new StringBuilder();
                sb.AppendLine("<div>");
                sb.AppendLine("<b>Authorization:</b>");
                sb.AppendLine("<ul>");
                foreach (string policy in policies.OrderBy(s => s))
                {
                    sb.Append("<li>").Append(HttpUtility.HtmlEncode(policy)).AppendLine("</li>");
                }
                sb.AppendLine("</ul>");
                sb.AppendLine("</div>");

                operation.Description  = sb.ToString();
            }
        }
    }
}

And then inside your "Startup" class:

services.AddSwaggerGen(c =>
{
    // ...
    c.OperationFilter<AuthorizationMarkupFilter>();
}

I've ripped this out of some bigger solution, so I hope it compiles. But you get the picture, I hope.

  • Related