Secure your Swagger

    July, 2017

    A typical day of a .NET developer includes creating Web API services by using some of the most popular frameworks.  What should we do with the documentation created in the process, how do we create something useful for developers who might need to use our services? There are two ways to create this type of documentation, the first of course is the manual way and thus hard to keep it perfectly synchronized with the API, and the second and simpler way of creating the documentation is from the code itself by using Swagger or Asp.Net Web API help pages and etc.

    Swagger is a framework for describing our API using a common language that everyone can understand. There are two ways to use this framework, the first approach is to create the design without creating any code and the second approach is when we have an API code ready, but we need to add a certain specification for the future use of the API functionalities. In this example we will look at the code first approach, but it does not mean that part of the same concept can not be used for a different approach.

    When it comes to corporate projects, this kind of specification should be available only to a certain group of developers, but Swagger framework in the default settings does not give this kind of protection. If by installing Swagger we have already done authorization and authentication of our Web API methods, through Swagger UI we can see that not every request we try is authorized, so what can we do?

    Authenticate your users to use Swagger UI

     

    After installing Swashbuckle Nuget package to your Web API project you will notice a new file called SwaggerConfig.cs under App_Start folder.

     

    The initial SwaggerConfig class contains one static method where we should register configuration dependencies and it looks similar to the following code with a lot of commented code inside.

    In addition, if we look in the commented code, we can see a lot of configuration code and configuration for individual users’ authorization, registered to our Web API, is not present. For that purpose we can create a custom authorization service with JavaScript, CSS and HTML by enabling them in .EnableSwaggerUi(c=>{}) expression in the Register method.

    Prior to this make sure you created a new folder named CustomSwagger and add a HTML file in the folder with the name index.html, JavaScript file named Auth.js and CSS file with name custom.css. You can copy the content from the UI when you navigate to your Web API project /swagger, by using browser developer tools. Make sure that you copied all HTML code from index into the newly created index.html file.

    After coping the content make a right click on index.html file and set it up like embedded resource making sure that the file will be always copied. Also for the purpose of login, we can add a new HTML file named login.html as the index.html registered in the configuration method and marked as embedded resource, which must be set as copy always.

    In addition, we must register the configuration expression, so the register method looks like this:

    Due to the static value of the variable “curl” we received from copying, we must make some changes in the script section of the index.html file in order to configure the real path of JSON data which is provided by the Swagger itself. So, add the following code at the beginning of the script section and on configuration variable (window.swashbuckleConfig) assign the new “curl” variable to the parameter rootUrl.

    After initial setup of the index file we can go on with the login form and the authentication token from the web API itself, now we can see that we have two HTML files where the main Swagger API documentation is on the /swagger/ui/index route and the login route is on the /swagger/ui/login. For authorization purposes, we can add user authentication check up in the index file in the section script at the bottom of the script, where we will check the token itself and its expiration. If the token is valid than we can assign its value to the input_apiKey field and we can tell the Swagger that we have a valid API communication token.

    Login page can contain a simple login form and a JavaScript logic, which will communicate with the token endpoint of the API. The script itself can be contained in the Auth.js file, which is a part of the CustomSwagger folder, and we can add it with the following line of code:

    If we want to use jquery we can also add it from the lib folder which is exposed from the Swagger itself.

    The Auth.js logic should be the same as the one that announces the users in the real application and after the successful validation of the valid token it will be redirected to the /index. Please keep in mind to get the right path to the generation token at the end.

    After we finally finished the main authentication over the Swagger and only authenticated users can now access our API documentation,  do we need all kind of users to access our documentation? If the answer is NO, than we can restrict the view of allowed operations.

    To achieve this, we must provide operation schemes, where we can define whether the API method will be visible or not for the current user to the Swagger UI, for that purpose we must provide SwaggerOperation schemes. All this means that the Swagger UI approach for each API method will not be restricted to users who have roles specified in the Schemes, while the remaining user roles specified in the authorize attribute will have access to the execution of the method only and they will not be able to see the method in the Swagger UI.

    In order to find out the current roles of the user who accesses the documentation, we can create two classes that will be used in one particular controller. The SwaggerTagAttribute class will inherit from AuthorizeAttribute and will override the OnAuthorization method in order to take the current role of the user. The controller itself will be disconnected from the Swagger UI with a special attribute contained in one method.

    This controller should also be called from the UI part of the documentation and for that purpose we can change the code block that is responsible whether the user has a valid authentication token.

    The way of resolving access to part of the documentation can be performed by implementing the IDocumentFilter interface. We will register the new class in the configuration section for the Swagger specification. In this class, we check that the current role of the user is contained in each SwaggerOperation Schema for each method that may be of type GET, POST, PUT, DELETE, PATCH, OPTIONS and HEAD. We can achieve this by checking all possible paths that are part of the API project. That way we extend the http or https access schemes to the level where we define which user’s parts of the API functionality have access to a specific part of the specification.

    The final configuration section for the Swagger specification should look like the following code:

    Dragan Bozhinovski,

    Sr. Technical Consultant