Request Schema Validation in Azure API Management

 For those of use that use or have implemented an Azure API Management instance, one feature that we have all looked for is a way to perform "Request Schema Validation" for incoming requests. Quite strangely, this much wanted feature is not a part of Azure API Management yet, although, there has been a User Voice request open since 2016 but the item is still marked as "Under Review". If you want to vote for this feature, you can Vote Here.

Although this feature has not been picked up by Microsoft engineers yet, this has not in any way dampened the enthusiasm around Azure API Management as an API Management tool. And as with most things, the community adapted and found workarounds to achieve what they otherwise expected out of the box.

In this blog, I will first describe the most common workaround and also the limitations that you might run into with it. Then of course, I will share how I circumvented this limitation with another workaround.

Using a Logic App

The most common and simplest approach to validating request schema is to create a http triggered logic app where you pass the request payload, download the schemas and validate the payload against the schema. A very simple 3-step process.

Logic App Download Schema from APIM

I am passing all parameters required to fetch the schema from API Management as headers with the HTTP request to call my Logic App. Then I form the URL to the Azure Management API to download the schemas for the API in question. Note that we also use Azure AD OAuth to authenticate our request to the Management API.

@{concat('https://management.azure.com/subscriptions/', triggerOutputs()?['headers']?['subscriptionId'], '/resourceGroups/', triggerOutputs()?['headers']?['resourceGroupId'], '/providers/Microsoft.ApiManagement/service/', triggerOutputs()?['headers']?['apimInstanceId'], '/apis/', triggerOutputs()?['headers']?['apiId'], '/schemas/', triggerOutputs()?['headers']?['schemaId'], '?api-version=2019-01-01')}


Once we have the schemas, we can get a specific schema by parsing the response and simply use the "Parse JSON" action in logic apps to validate. Respond with a "HTTP422 - Unprocessable entity" when "Parse JSON" fails otherwise respond with a HTTP200.
The specific schema must also be passed as header.

This all looks good until the time your API schema definitions start to grow and you start introducing schema references to structure your schema definitions and introduce reusability. The "Parse JSON" action in Logic Apps does not resolve references. So, your logic app that worked so well for you so far is suddenly deemed useless.

At this point, the obvious way forward is to take things in your own hand and introduce a similar implementation using an Azure Function - and yes, you can use resolvers here.

Using Azure Function

One of the first mistakes I made when writing my function was the most obvious with JSON and .Net. I tried to use Json.Net. This did not work because soon I realized that the format in which API Management returned the schemas from the Management API was no ordinary JSON schema. It was in fact, Open API format. As most of us know, although Open API and JSON schema are  slowly becoming more and more interoperable, they still have their differences. And this is why, Json.Net resolvers just could not resolve the inline references or validate against the unresolved schemas.

One of the best libraries for working with Swagger definitions and Open API has been NSwag by Rico Suter (cannot thank him enough for the library) and it uses NJsonSchema (also by Rico Suter) under the hood, this library makes schema validation a breeze for Open API formats.

An aspect that I had to deal with in the function was that the schemas I downloaded from API Management were not fully Open API standard. So, I had to do the bare minimal to convert it to an Open API document.


Calling Function from API Policy



Full code for the function on my Github.

Comments

Popular posts from this blog

Automate Import of Functions/WebAPI in Azure API Management as backend and using OpenAPI definition and Terraform

Transcripts with Microsoft Bot Framework v4

Managing built-in cache in Azure API Management