Azure API Management Policies: 7 Guardrails

Azure API Management policies are the XML bouncers between your consumers and your backend APIs. Designed well, they validate tokens, smooth traffic spikes, keep browser clients honest and keep secrets out of reach. Designed casually, they turn APIM into an expensive request-forwarding service.

Here are seven practical guardrails. They don’t replace backend security; they make the gateway do gateway work well so your apps can focus on business logic.

Where Azure API Management policies fit

Policies run in the gateway, in four sections:

  • Inbound: validate, normalize, throttle, route and authenticate before the backend sees the request.
  • Backend: behavior while forwarding.
  • Outbound: shape the response before it returns.
  • On-error: controlled handling of gateway errors.

API policy flow

1. Caller
App, user or service
2. Inbound
JWT, CORS, throttle
3. Backend
Route and auth
4. API backend
App, function or service

Policies change runtime behavior without rebuilding backends. That’s the power, and the risk: a broad global policy affects every API.

1. Preserve inherited policies with <base />

Policies apply at global, workspace, product, API and operation scope. Microsoft recommends a <base /> element at the start of each section so child scopes inherit parent policies. Without it, an operation-level edit can silently bypass a global control.

<policies>
  <inbound>
    <base />
    <!-- Operation-specific policies go here -->
  </inbound>
  <backend>
    <base />
  </backend>
  <outbound>
    <base />
  </outbound>
  <on-error>
    <base />
  </on-error>
</policies>

If an API seems to ignore a policy, check the effective policy view in the portal to confirm inheritance isn’t skipped.

2. Validate tokens before the backend works

validate-jwt enforces a valid JWT from a header, query parameter or token value; for Entra tokens, validate-azure-ad-token is purpose-built. Reject bad identity signals early, checking issuer, audience, expiry, required claims and the Bearer scheme:

<validate-jwt header-name="Authorization"
              require-scheme="Bearer"
              failed-validation-httpcode="401"
              failed-validation-error-message="Invalid or missing access token">
  <openid-config url="https://login.microsoftonline.com/{tenant-id}/v2.0/.well-known/openid-configuration" />
  <audiences>
    <audience>api://your-api-app-id</audience>
  </audiences>
  <issuers>
    <issuer>https://login.microsoftonline.com/{tenant-id}/v2.0</issuer>
  </issuers>
</validate-jwt>

Gateway validation doesn’t replace authorization in the API. Object-level checks belong in the backend, which understands the business object. For 401 troubleshooting, see Azure API Management JWT validation.

3. Rate-limit by the right key

rate-limit-by-key limits calls per key over a renewal period and returns 429 Too Many Requests when exceeded. The design choice is the key:

Counter keyGood forWatch out for
context.Request.IpAddressPublic or anonymous APIs, quick abuse controlsNAT can make many users look like one caller.
Subscription IDDeveloper portal and product-based APIsOnly useful where subscription keys are part of the design.
JWT claimPer-app, per-user or per-tenant limitsValidate the token before trusting its claims.
<rate-limit-by-key calls="120"
                   renewal-period="60"
                   counter-key="@(context.Request.IpAddress)"
                   remaining-calls-header-name="x-ratelimit-remaining"
                   retry-after-header-name="Retry-After" />

Microsoft notes throttling is distributed and not perfectly precise, so treat it as an operational control, not a billing meter. Choose the control to match the goal: rate limits for short spikes, quotas for longer-term allowances, and concurrency limits for fragile backends.

4. Make CORS intentionally boring

The cors policy handles cross-origin browser access at the gateway. Microsoft’s reference flags common issues: policy order, header-based subscription keys at product scope, and overly permissive wildcards.

  • Place cors early in the inbound section.
  • Avoid * unless the API really serves any origin.
  • List explicit origins, and only the methods and headers clients need.
  • Test preflight (OPTIONS) requests separately.
<cors allow-credentials="false" terminate-unmatched-request="true">
  <allowed-origins>
    <origin>https://apps.contoso.com</origin>
  </allowed-origins>
  <allowed-methods preflight-result-max-age="300">
    <method>GET</method>
    <method>POST</method>
  </allowed-methods>
  <allowed-headers>
    <header>authorization</header>
    <header>content-type</header>
  </allowed-headers>
</cors>

5. Use managed identity carefully

authentication-managed-identity gets an Entra token for a target resource and sets it as a Bearer token, removing hardcoded secrets from gateway-to-backend calls. Microsoft warns that users who can edit policies may misuse the token if permissions and scopes are too broad.

<authentication-managed-identity resource="https://vault.azure.net" />
  • Grant the identity only the permissions the backend call needs.
  • Prefer API or operation scope over global when one API needs the token.
  • Review who can edit policies, not just who deploys APIs.
  • Use backend entities and routing so tokens only reach trusted services.

See Azure API Management managed identity troubleshooting for when the permissions, network path or scope are slightly wrong.

6. Add response headers on purpose

set-header adds, overrides, appends or deletes headers. Useful candidates: x-correlation-id for support tickets, version or deprecation hints during migrations, security headers for browser-facing APIs, and remaining-call headers so clients back off before a 429.

<set-header name="x-gateway-region" exists-action="override">
  <value>@(context.Deployment.Region)</value>
</set-header>

Some headers, including Connection, Content-Length, Keep-Alive and Transfer-Encoding, can’t be overridden, appended or deleted.

7. Build a troubleshooting checklist before the outage

  • Confirm the effective policy includes parent controls.
  • Validate JWT issuer, audience and required claims.
  • Test CORS preflight separately.
  • Check the rate-limit counter key and scope.
  • Review managed identity permissions and policy edit rights.
  • Use correlation headers and logs for repeatable support.

API policies protect runtime behavior; Azure Resource Graph queries catch configuration drift across the estate.

A baseline Azure API Management policies pattern

A simplified pattern combining inheritance, CORS, token validation, rate limiting and a header. Adapt the values to your tenant and clients.

<policies>
  <inbound>
    <base />
    <cors allow-credentials="false" terminate-unmatched-request="true">
      <allowed-origins>
        <origin>https://apps.contoso.com</origin>
      </allowed-origins>
      <allowed-methods preflight-result-max-age="300">
        <method>GET</method>
        <method>POST</method>
      </allowed-methods>
      <allowed-headers>
        <header>authorization</header>
        <header>content-type</header>
      </allowed-headers>
    </cors>
    <validate-jwt header-name="Authorization"
                  require-scheme="Bearer"
                  failed-validation-httpcode="401">
      <openid-config url="https://login.microsoftonline.com/{tenant-id}/v2.0/.well-known/openid-configuration" />
      <audiences>
        <audience>api://your-api-app-id</audience>
      </audiences>
    </validate-jwt>
    <rate-limit-by-key calls="120"
                       renewal-period="60"
                       counter-key="@(context.Request.IpAddress)"
                       remaining-calls-header-name="x-ratelimit-remaining" />
  </inbound>
  <backend>
    <base />
  </backend>
  <outbound>
    <base />
    <set-header name="x-gateway-region" exists-action="override">
      <value>@(context.Deployment.Region)</value>
    </set-header>
  </outbound>
  <on-error>
    <base />
  </on-error>
</policies>

Safe rollout

  1. Inventory global, product, API and operation policies.
  2. Stage changes on a non-production API or test operation.
  3. Validate auth, CORS, throttling and routing with real client patterns.
  4. Deploy narrowly, then widen scope once proven.
  5. Monitor 401, 403, 429 and backend error trends afterwards.

Last reviewed: October 2026

Sources


Discover more from Cloud Osprey

Subscribe to get the latest posts sent to your email.

Cloud Osprey
Cloud Ospreyhttps://cloudosprey.com/about/
Hands-on Microsoft cloud practitioner writing practical, source-checked guides on Microsoft 365, SharePoint, Copilot, Entra ID, Power Platform and Azure. Formerly the author of SP Monkey, the SharePoint and Microsoft 365 blog, since 2016. Every guide links its sources and carries a "Last reviewed" date.

Recent Articles

Related Stories