Base solution for your next web application
Open Closed

Swagger Filter End Points By Permission [Code Provided] #3608


User avatar
1
bbakermmc created

Incase anyone is looking to filter the Swagger UI to prevent showing End Points for users who don't have permissions.

Note: In this case its checking for explicit permissions (Our use case). If you want it to show end points w/no permissions you will need to adjust it.

startup.cs

services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new Info { Title = "Platform API", Version = "v1" });
                options.DocInclusionPredicate((docName, description) => true);
                options.DocumentFilter<SwaggerAbpAuthorizeAttributeAuthorizationFilter>();
            });
new class file
public class SwaggerAbpAuthorizeAttributeAuthorizationFilter : IDocumentFilter
        {          
            private readonly IPermissionChecker _permissionChecker;

            public SwaggerAbpAuthorizeAttributeAuthorizationFilter( IPermissionChecker permissionChecker)
            {
                _permissionChecker = permissionChecker;
            }

            public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
            {
                var descriptions = context.ApiDescriptionsGroups.Items.SelectMany(group => group.Items);

                foreach (var description in descriptions)
                {
                  var authAttributes = description.ControllerAttributes()
                        .OfType<AbpAuthorizeAttribute>()
                        .Union(description.ActionAttributes()
                            .OfType<AbpAuthorizeAttribute>());

                    // check if this action should be visible
                    var forbiddenDuePermissions = IsForbiddenDuePermissions(authAttributes);

                    if (!forbiddenDuePermissions)
                        continue; // user passed all permissions checks

                    var route = "/" + description.RelativePath.TrimEnd('/');
                    var path = swaggerDoc.Paths[route];

                    // remove method or entire path (if there are no more methods in this path)
                    switch (description.HttpMethod)
                    {
                        case "DELETE":
                            path.Delete = null;
                            break;
                        case "GET":
                            path.Get = null;
                            break;
                        case "HEAD":
                            path.Head = null;
                            break;
                        case "OPTIONS":
                            path.Options = null;
                            break;
                        case "PATCH":
                            path.Patch = null;
                            break;
                        case "POST":
                            path.Post = null;
                            break;
                        case "PUT":
                            path.Put = null;
                            break;
                        default: throw new ArgumentOutOfRangeException("Method name not mapped to operation");
                    }

                    if (path.Delete == null && path.Get == null &&
                        path.Head == null && path.Options == null &&
                        path.Patch == null && path.Post == null && path.Put == null)
                        swaggerDoc.Paths.Remove(route);
                }
            }

            private bool IsForbiddenDuePermissions(IEnumerable<AbpAuthorizeAttribute> attributes)
            {
                var authorizeAttributes = attributes
                    .Where(p => p.Permissions != null).ToList();

                var permissions = new List<string>();
                if (authorizeAttributes.Count != 0)
                {
                    foreach (var authorizeAttribute in authorizeAttributes)
                    {
                        permissions.AddRange(authorizeAttribute.Permissions.ToList());
                    }
                }
                else
                {
                    return true;
                }

                foreach (var permission in permissions)
                {
                    var allow = _permissionChecker.IsGranted(permission);
                    if (allow)
                    {
                        return false;
                    }
                }

                return true;
            }
        }

1 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Thanks @BBakerMMC :)