In last few articles, I have been explaining my thoughts about API management. Till now, below topics are covered.
- Introduction to API Management
- How to create API Management instance
- How to publish APIs through API Management instance
- What are policies and how to apply policies in API Management
Security is a wide term !
This article to cover my thoughts on API Management from security perspective.
Security is very wide term and there can be a lot of strategies to make your APIs secure. Some of the strategies for applying security can be:
- IP whitelisting – to allow calls only from specific IPs
- Authentication – to know who is calling the APIs
- Authorization – to check if the user is allowed to access the API
Please note that this article does not provide information on all possibilities. But this article provides high level information on how authentication can be applied on APIM APIs, and how APIs can be protected from overuse.
Before we get started, you will need to Azure Portal access to understand the topic. If you do not have access, then you can create free account on Azure.
JWT Token Based Authorization
JWT token can be used for authentication purpose. Policy can be configured in API management to check if JWT token is valid. The policy can also check if the JWT token has required claims.
This policy can be configured as inbound policy so that it gets executed when API management API is called.
Below is the sample of the policy. For the sake of simplicity, only JWT validation policy is added in inbound section. Rest of the sections are not shown.
<inbound>
<validate-jwt header-name="Authorization">
<issuer-signing-keys>
<key>{{your-signing-key}}</key>
</issuer-signing-keys>
<required-claims>
<claim name="{{your-claim-name}}">
<value>{{expected-value-in-claim}}</value>
</claim>
</required-claims>
</validate-jwt>
</inbound>
Please note that this JWT token should be provided by API consumers to the API Management.
Basic Authentication with Backend Service
If you choose to apply this strategy, you will have to add below policy to authenticate with the Backend API. Once below policy is added in inbound collection, API management will add a basic header while calling the Backend API.
Please note that the consumers which are calling API Management API does not need to know this username and password. The basic authentication header would be added by APIM.
<inbound&;gt; <authentication-basic username="user" password="pwd" /> <inbound>
Certificate Authentication with Backend Service
This policy enables to authenticate with backend API using a client certificate. The certificate is identified based on thumbprint.
<inbound> <authentication-certificate thumbprint="...." /> <inbound>
Please note that this client certificate should be installed in API Management first before enabling it on APIs.
Please note that the consumers which are calling API Management API does not need to know this client certificate. The certificate is attached with request by APIM before calling Backend API.
OAuth2 Authentication with Backend Service
If your backend API is already secured with OAuth2.0 using any platform, then the API consumers should pass the Authorization header to the API management.
The authorization token should be acquired by API consumer by calling appropriate OAuth provider (e.g. Google, facebook, Microsoft, etc.).
You do not need to add any policy in the API Management. The header would be sent by API Consumer and API Management would send the same header to the Backend API.
Prevent Excessive Usage
Rate and Quota limit policy can help to avoid excessive the usage of the APIs published through API management.
For limiting call rate there are two policies, rate limit by key and rate limit by subscription.
Below examples shows call rate limit by key (xml element rate-limit-by-key) and call rate limit by subscription (xml element rate-limit).
You should use any one (or both) depending on your business requirements.
Below policy states that there are only 20 calls allowed in 90 seconds.
<rate-limit calls="20" renewal-period="90" />
Below policy shows example of limiting the call rates by some key. It is limiting calls from given IP Address to 10 successful calls (where status code is 200) per 60 seconds.
Please note that key can be any arbitrary string or it can be set using the policy expressions.
<rate-limit-by-key calls="10" renewal-period="60" increment-condition="@(context.Response.StatusCode == 200)" counter-key="@(context.Request.IpAddress)"/>
The quota policy enforces a renewable or lifetime call volume and/or bandwidth quota, on a per subscription basis. You can also use quota-by-key as shown in below example.
<quota calls="number" bandwidth="kilobytes" renewal-period="seconds"> <api name="API name" id="API id" calls="number" renewal-period="seconds" /> <operation name="operation name" id="operation id" calls="number" renewal-period="seconds" /> </api> </quota> <quota-by-key calls="number" bandwidth="kilobytes" renewal-period="seconds" increment-condition="condition" counter-key="key value" />
Restricting Caller IPs
API management allows you to specify either whitelist or blacklist of the IP addresses. Below is an example of how to configure this policy:
<ip-filter action="allow | forbid"> <address>address</address> <address-range from="address" to="address" /> </ip-filter>
Prevent Content Attack
For applying this strategy, you will need to perform some data anlaysis. You can check how much should be the maximum allowed size of request to API Management. Once this is decided, you can add a policy to reject any request (or redirect to alternate host of backend API) which has content size more than maximum allowed request size.
Below is an example of the policy. It redirects the URL to other backend service host if the content size is more than 256000 bytes.
<set-variable name="bodySize" value="@(context.Request.Headers["Content-Length"][0])"/> <choose> <when condition="@(int.Parse(context.Variables.GetValueOrDefault<string>("bodySize"))<256000)"> <!-- let it pass through by doing nothing --> </when> <otherwise> <rewrite-uri template="{{alternate-path-and-query}}"/> <set-backend-service base-url="{{alternate-host}}"/> </otherwise> </choose>
Similar to this you can also add return response and send error in the response in case you do not want to process the request which is more than the maximum allowed size.
Watch Abnormal Activity
You can redirect the logs to Event Hub service. Then you can write any automated logic or manual task to check the logged contents and then you can check if there is any abnormal activity. If any such activity is found, then you can trigger an email notification to notify appropriate stakeholders.
Below is the sample showing syntax for this policy:
<log-to-eventhub logger-id="id of the logger entity" partition-id="index of the partition where messages are sent" partition-key="value used for partition assignment"> @{ Expression returning a string to be logged } </log-to-eventhub>
Refer this MSDN documentation for more details
I hope this article has provided sufficient information for you to get started on the security of APIs published through API management. I would really like to know your experiences as well. Please do comment and let me know your thoughts.