Securing APIs with API Management
Security Layers
A robust API security strategy involves multiple layers:
- Network Security — VNET integration, Private Endpoints
- Authentication — Who is calling the API?
- Authorisation — What are they allowed to do?
- Encryption — TLS for data in transit
- Throttling — Prevent abuse
Subscription Keys
The simplest authentication method. Every APIM product can require a subscription key:
- Passed via
Ocp-Apim-Subscription-Keyheader orsubscription-keyquery parameter - Generated per subscription (primary and secondary for rotation)
- Can be scoped to All APIs, a single Product, or a single API
Important: Subscription keys alone are not sufficient for production APIs. Combine with OAuth 2.0 or client certificates.
OAuth 2.0 / OpenID Connect
Validating JWT Tokens
<validate-jwt header-name="Authorization" require-scheme="Bearer"
failed-validation-httpcode="401" failure-message="Unauthorised">
<openid-config url="https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration" />
<audiences>
<audience>{api-app-id}</audience>
</audiences>
<issuers>
<issuer>https://login.microsoftonline.com/{tenant}/v2.0</issuer>
</issuers>
<required-claims>
<claim name="roles" match="any">
<value>API.Read</value>
<value>API.Write</value>
</claim>
</required-claims>
</validate-jwt>
Extracting Claims for Backend
<set-header name="X-User-Id" exists-action="override">
<value>@(context.Request.Headers.GetValueOrDefault("Authorization","")
.AsJwt()?.Claims.GetValueOrDefault("oid", "unknown"))</value>
</set-header>
Client Certificates (mTLS)
For service-to-service authentication:
<choose>
<when condition="@(context.Request.Certificate == null ||
context.Request.Certificate.Thumbprint != "expected-thumbprint")">
<return-response>
<set-status code="403" reason="Forbidden" />
</return-response>
</when>
</choose>
Managed Identity
Use APIM's managed identity to authenticate to backend services:
<authentication-managed-identity resource="https://management.azure.com/" />
This eliminates the need to store credentials in APIM configuration.
Network Security
VNET Integration (Premium Tier)
- External mode — Gateway accessible from internet, backend in VNET
- Internal mode — Gateway only accessible within VNET
Private Endpoints
Available on Premium tier for fully private API access.
API Scopes and Permissions
Configure API Permissions in Azure AD
1. Register API application in Azure AD
2. Define App Roles or OAuth 2.0 scopes:
- API.Read — Read access to API resources
- API.Write — Write access to API resources
- API.Admin — Administrative operations
3. Configure client application permissions
4. Validate in APIM using validate-jwt policy
Role-Based Access in Policies
<validate-jwt header-name="Authorization" require-scheme="Bearer">
<openid-config url="https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration" />
<required-claims>
<claim name="roles" match="any">
<value>API.Read</value>
</claim>
</required-claims>
</validate-jwt>
<!-- Check for write permission on POST/PUT/DELETE -->
<choose>
<when condition="@(new [] {"POST","PUT","DELETE"}.Contains(context.Request.Method))">
<validate-jwt header-name="Authorization" require-scheme="Bearer">
<openid-config url="https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration" />
<required-claims>
<claim name="roles" match="any">
<value>API.Write</value>
</claim>
</required-claims>
</validate-jwt>
</when>
</choose>
Microsoft Reference: Protect APIs with Azure AD
IP Allowlisting and Geo-Filtering
IP Allowlisting
<ip-filter action="allow">
<address>203.0.113.10</address>
<address-range from="10.0.0.0" to="10.0.0.255" />
</ip-filter>
Geo-Filtering
<choose>
<when condition="@(new [] {"CN","RU","KP"}.Contains(context.Request.Headers.GetValueOrDefault("X-Forwarded-For-Country","")))">
<return-response>
<set-status code="403" reason="Forbidden" />
<set-body>Access denied from this region</set-body>
</return-response>
</when>
</choose>
WAF Integration
Deploy Azure Application Gateway with Web Application Firewall (WAF) in front of APIM:
Client → Application Gateway (WAF) → APIM → Backend APIs
WAF protects against:
- SQL injection
- Cross-site scripting (XSS)
- Command injection
- HTTP protocol violations
- OWASP Top 10 threats
Microsoft Reference: APIM with Application Gateway
Best Practices
- Never rely solely on subscription keys — add OAuth 2.0 or mTLS
- Rotate keys regularly — use primary/secondary key pattern
- Use Managed Identity for backend authentication
- Enable TLS 1.2+ and disable older protocols
- Implement rate limiting to prevent abuse
- Use VNET integration for internal APIs in production
- Validate all input — use
<validate-content>policy for request body validation - Log security events to Application Insights and Log Analytics
- Use Application Gateway WAF for external-facing APIs
- Implement CORS policies restrictively — only allow known origins
- Use certificate pinning for critical service-to-service communication
- Regular security audits — review policies and access controls quarterly