Using swagger/swashbuckle .net core operation filters to enable API testing

The Problem 

The problem arises in solutions which contains identity servers based on OAuth2 and OpenId protocols (For example Identity Server, WSO2 identity cloud, etc) and Rest API with swagger swashbuckle used for auto documenting and testing. Each API call should contain authentication token otherwise testing API ("Try it out") will not work.

Solution

One of the option to enable API testing ("Try it out" button) is using swagger operation filter. In example below was created operation filter which includes Bearer authentication token field to HTTP header of each API calls.

 public class AuthorizationHeaderOperationFilter : IOperationFilter
 {
        public void Apply(Operation operation, OperationFilterContext context)
        {
            IList<FilterDescriptor> filterDescriptors = context.ApiDescription.ActionDescriptor.FilterDescriptors;
            bool isAuthorized = filterDescriptors.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
            bool allowAnonymous = filterDescriptors.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);

            if (isAuthorized && !allowAnonymous)
            {
                if (operation.Parameters == null)
                {
                    operation.Parameters = new List<IParameter>();
                }

                operation.Parameters.Add(new NonBodyParameter
                {
                    Name = "Authorization",
                    In = "header",
                    Description = "access token",
                    Required = true,
                    Type = "string",
                    Default = "Bearer "
                });
            }
        }
 }

Then filter should included in swagger swashbuckle configuration in ConfigureServices method of Startup.cs file.

 services.AddSwaggerGen(setupAction =>
 {
     setupAction.SwaggerDoc("v2", new Info { Title = "DeviceAPI", Version = $"v2", Description = "The Device API" });
     // Filter Registration
     setupAction.OperationFilter<AuthorizationHeaderOperationFilter>();
 });

Testing

To test/demonstrate this solution I've created API controller with source code below.

 [Route("api/[controller]")]
 public class DevicesController : Controller
 {
        [HttpGet("{deviceId}")]
        [Authorize]
        public async Task<IActionResult> Get(string deviceId, [Required]string deviceName)
        {
            if (!this.ModelState.IsValid)
            {
                return new BadRequestObjectResult(this.ModelState);
            }

            return new OkResult();
        }
 }

Then next step will be obtain bearer authentication token from identity server (I've used IdentityServer 4 but algorithm for other identity services will be almost the same). I've used postman to get authorization token.


 
 And final step is start application, pass authentication token (other api parameters) to API call (in my case it get device by id) and push "Try it out" button.
 This process are shown in image below.

  

That's it.

Disclaimer  

This article doesn't describe the process of setting up swashbuckle or web api etc. Following link can help to do it: 
 

Comments