Using access tokens in Swagger with Swashbuckle

Securing access to your API using access tokens is common practice. In this post, we’ll learn how to call secure API endpoints using the swagger specification specifically using Swashbuckle (An implementation of Swagger for .NET)

Understanding Swagger Schema:
This outline shows the basic structure of a swagger specification document. This file is represented in Json which is in turn used by Swagger-UI to display the interactive API documentation.
{
"swagger": "2.0",
 "info": {
"version": "v1",
"title": ".NET Latest API",
"description": ".NET Latest API",
"termsOfService": "Some terms",
"contact": {
"name": "donetlatest Team",
"email": "team@dotnetlatest.com"
}
},"host": "local.api.donetlatest.com:80",
"schemes": [

"http"

],"paths": {

"/V1/api/Authentication": {},
"/V1/api/Countries": {},
"/V1/api/Clients": {
},"definitions": {

"CountryDTO": {},
"StateDTO": {},
"ClientDTO": {}
}
}

 

Parameters
The Paths item object describes the operations on a single path. Each path has a parameters object which are a list of inputs for a given endpoint.
"/V1/api/LitmusClients": {
"post": {
"tags": [
"LitmusClients"
],
"summary": "GET /api/clientsrn Gets an array of all clients",
"operationId": "Clients_Index",
"consumes": [
],
"produces": [
"application/json",
"text/json"
],
"parameters": [
{
"name": "Authorization",
"in": "header",
"description": "access token",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/ClientDTO"
}
}
}
},
"deprecated": false
}
}
}

 Types of Parameters

  • Path – Used together with  Path Templating
  • Query – Parameters that are appended to the URL
  • Header – Custom headers that are expected as part of the request
  • Body – The Payload that’s appended to the HTTP request.
  • Form – Used to describe the payload of an Http request
The swagger specification describes in detail about parameter types and how you can configure them. https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md
Extending Swagger to add a new parameter:
Swashbuckles implementation of swagger reads XML code comments to generate the required swagger specification. Unfortunately, if you require an authorization header (access token) to make requests, the XML code comments cannot provide this info to Swashbuckle. You’ll have to manually inject this new parameter during swagger specification generation.
Swashbuckle provides an interface called IOperationFilter  to apply new parameters. Implementing this interface will look something like this.
public class AddAuthorizationHeaderParameterOperationFilter: IOperationFilter
    {
        public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
        {
            var filterPipeline = apiDescription.ActionDescriptor.GetFilterPipeline();
            var isAuthorized = filterPipeline
                                             .Select(filterInfo => filterInfo.Instance)
                                             .Any(filter => filter is IAuthorizationFilter);

            var allowAnonymous = apiDescription.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any();

            if (isAuthorized && !allowAnonymous)
            {
                operation.parameters.Add(new Parameter {
                    name = "Authorization",
                    @in = "header",
                    description = "access token",
                    required = true,
                    type = "string"                    
                });
            }
        }
    }
public class SwaggerConfig
    {
        public static void Register()
        {
            var thisAssembly = typeof(SwaggerConfig).Assembly;

            GlobalConfiguration.Configuration
                .EnableSwagger(c =>
                   
                   
                    c.SingleApiVersion("v1", "Wordfly API").Description("An API for the wordfly messaging platform")
                            .TermsOfService("Some terms")
                            .Contact(cc => cc.Name("Wordfly Team")
                            .Email("team@wordfly.com"));
                                                                          
  c.OperationFilter(() => new AuthorizationHeaderParamterOperationFilter()));
                   
                    c.IncludeXmlComments(GetXmlCommentsPath());
          }
     }

s