Designing and composing APIs is a very subjective matter and there are many ways to success (and even more to failure). One approach I’ve always liked is the way MuleSoft describes it. They define three layers of APIs:
- Experience APIs: purpose-built APIs for specific apps, also known as BFFs (Backend for Frontend)
- Process APIs: domain-driven business functions that are exposed as a consistent set of APIs
- System APIs: the standard API endpoints of your backend systems: legacy or modern SaaS applications
Almost every environment will require – sooner than later – some kind of API layering. This blog post describes some important aspects on how you can achieve this within Azure API Management.
Indicating the API layer
Azure API Management does not have a concept of layers out-of-the-box. If you apply some kind of layering, I’m convinced that it should be clear to everyone to which layer a certain API belongs. By making this explicit, it requires a first analysis about the scope and purpose of the API. A clean way to indicate the API layer, is by leveraging a simple naming convention:
Another way to achieve this, is by leveraging the API Tags that are available in API Management:
On Twitter, I received the feedback of Chris that Products are also good to indicate API layers. Whilst I’ve never implemented it that way, it looks like a solid approach to me. Definitely because you can share policies across all APIs that belong to the same layer (product).
Routing
If you want to route an API request from one API to another, you preferably don’t call the external DNS of Azure APIM again, because this will require an additional network hop. Next to that, firewall rules might block this, in case your API Management instance is protected by a Virtual Network. The simplest and fastest way to call another API that is exposed on the same API Management instance, is by calling its address via localhost. In this way, you remain inside the same gateway. If you want to do this, it is required to set the Host HTTP header, as described in this detailed blog post.
<!--Set hostname for interal routing to system-api--> <set-header name="Host" exists-action="override"> <value>your-apim-name.azure-api.net</value> </set-header> <!--Point to salesforce-api--> <set-backend-service base-url="https://localhost/salesforce-api/v2" />
Security
Even when you perform such localhost-routing, the APIs that you consume have to be secured. In many organizations, I implement the strategy that system APIs can only be consumed by other APIs in API Management. To make that security as seamless as possible, I leverage managed identity.
The process API that calls the system API can use this secure one-liner.
<!--Managed identity to authenticate against system API--> <authentication-managed-identity resource="https://management.azure.com/"/>
Remark that I am abusing the default https://management.azure.com/ enterprise application for this. This can also be a dedicated application within Azure AD.
The system API implements this security, to only allow calls from API Management itself.
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized" require-expiration-time="true" require-scheme="Bearer" require-signed-tokens="true"> <openid-config url="https://sts.windows.net/{{apim-tenant-id}}/.well-known/openid-configuration" /> <audiences> <audience>https://management.azure.com/</audience> </audiences> <required-claims> <claim name="appid" match="any"> <value>{{apim-identity-client-id}}</value> </claim> </required-claims> </validate-jwt>
Monitoring
When you implement such a layered design, monitoring is key. In case your API Management is not optimized for monitoring, it will become an unmanageable black box that is extremely hard to troubleshoot, especially those inter-API communications. However, if you configure Application Insights, you can leverage the native API monitoring that gives a very clear view on those API-to-API interactions:
Conclusion
Any kind of layered API design is possible within Azure API Management. Personally, the biggest advantage is the fact that you can split more clearly the frontend configuration from the backend configuration. If you don’t apply this strategy, your APIs often contain policies that handle both the frontdoor and backdoor security or transformation logic. This is a very interesting and subjective topic, so don’t hesitate to share your vision on this matter!
Cheers!
Toon