Azure API Management JWT validation looks simple in a diagram, then starts returning 401 Unauthorized late on a Friday. Most failures come from a short list: wrong audience, issuer mismatch, missing bearer scheme, stale signing keys, confused v1/v2 Entra endpoints, or an overly strict claim check.
This runbook shows how to validate tokens with API Management policies, troubleshoot failures and add guardrails.
Azure API Management JWT validation flow
Gets an access token
Validate token policy
Receives a trusted request
The gateway rejects bad tokens before the backend spends CPU and logs on them.
When to use Azure API Management JWT validation
Use it when callers must present a valid access token before APIM forwards the request. Microsoft documents two related policies:
validate-azure-ad-token: purpose-built for JWTs issued by Microsoft Entra ID.validate-jwt: generic validation for Entra ID or any OpenID Connect provider.
For Entra-only APIs, start with validate-azure-ad-token. Use validate-jwt for partner, B2C or third-party providers, custom signing keys, or a generic OpenID configuration. Either way, validate identity at the edge and keep the backend focused on business logic.
Baseline policy for Microsoft Entra tokens
<validate-azure-ad-token
tenant-id="00000000-0000-0000-0000-000000000000"
header-name="Authorization"
failed-validation-httpcode="401"
failed-validation-error-message="Unauthorized. Access token is missing or invalid.">
<audiences>
<audience>api://your-api-application-id</audience>
</audiences>
<required-claims>
<claim name="scp" match="any" separator=" ">
<value>access_as_user</value>
</claim>
</required-claims>
</validate-azure-ad-token>
Put it in the inbound section at the narrowest sensible scope: operation if one endpoint differs, API if the whole API shares authorization, and product, workspace or global only when you genuinely want broad behavior.
Azure API Management JWT validation checklist
| Check | What to confirm |
|---|---|
| Token location | Usually the Authorization header with the Bearer scheme. Avoid query-string tokens. |
| Tenant and issuer | Match the tenant and endpoint version that issued the token; v1 and v2 claims differ. |
| Audience | aud matches the API’s Application ID URI expected by the policy. |
| Claims | Delegated scopes (scp), app roles (roles), client app IDs and separator settings. |
| Signing keys | OpenID metadata and JWKS are reachable; key rollover can expose stale-cache assumptions. |
| Clock skew | nbf and exp against real clocks; a little tolerance avoids false failures. |
What a 401 usually means
Policy failures return a deliberately vague 401. That’s good security and awkward debugging, so narrow it down:
| Symptom | Likely cause | What to check |
|---|---|---|
| Immediate 401 or “JWT not present” | Missing header, wrong header name or missing bearer scheme. | Confirm Authorization: Bearer <token>. With token-value, don’t include “Bearer” in the expression output. |
| Works in one environment only | Audience, tenant or issuer differs between app registrations. | Decode the token and compare aud, iss, tid, appid/azp, scp and roles. |
| Fails after an app registration change | Old token, or JWKS/OpenID metadata cache not yet refreshed. | Get a fresh token; Microsoft notes OpenID configuration including JWKS is cached and refreshed periodically. |
| User token passes, app-only token fails | Policy checks scp, but client credentials tokens use roles. | Match the claim check to the OAuth flow. |
| Policy saves but behaves oddly | Wrong scope or unexpected inherited policy order. | Review global, product, API and operation scopes. |
A safer generic validate-jwt pattern
With the generic policy, be explicit about the OpenID metadata endpoint, audience, issuer and required claims. A simplified pattern for Entra v2 tokens:
<validate-jwt
header-name="Authorization"
require-scheme="Bearer"
failed-validation-httpcode="401"
failed-validation-error-message="Unauthorized. Access token is missing or invalid."
clock-skew="60">
<openid-config url="https://login.microsoftonline.com/{tenant-id}/v2.0/.well-known/openid-configuration" />
<audiences>
<audience>api://your-api-application-id</audience>
</audiences>
<issuers>
<issuer>https://login.microsoftonline.com/{tenant-id}/v2.0</issuer>
</issuers>
<required-claims>
<claim name="scp" match="any" separator=" ">
<value>access_as_user</value>
</claim>
</required-claims>
</validate-jwt>
Guardrail: don’t loosen validation to make a failing client work. Fix the app registration, token request, scope or policy; “temporarily accept anything” has a way of becoming architecture.
Claims: scopes, roles, audiences and client IDs
- Delegated user flows usually include
scp, a space-separated scope list such asaccess_as_user. - Application permissions (client credentials) rely on
roles. audmust identify your API, not Microsoft Graph or a client app.issmust match the issuer pattern for the tenant and endpoint version.- Client app allow-lists help control callers but need maintenance when registrations change.
Use tracing carefully
APIM request tracing shows processing across inbound, backend, outbound and on-error phases, but it can expose sensitive data. Reproduce with a test caller and non-production token, capture the trace through the supported debug flow, inspect the failing inbound step (audience, issuer, claims, token extraction), then remove debugging access.
Runbook for a failing API
- Decode the token locally, not on a random website. Check
aud,iss,exp,nbf,scp,roles,tidand client claims. - Check policy scope and inheritance to confirm which policy actually runs.
- Compare the Entra app registration: exposed scopes, Application ID URI, app roles, access token version and supported account types.
- Request a fresh token after registration or permission changes.
- Trace only for the reproduction window, and treat output as sensitive.
- Document the working policy beside the app registration and deployment notes.
Production guardrails
- Change control: version policy XML in source control and promote through environments.
- Least scope: API or operation scope unless global is truly intended.
- Test tokens: keep known-good delegated and app-only cases for every protected API.
- Observability: watch for 401 spikes after app registration, certificate or policy changes.
Azure API Management JWT validation works best when it’s explicit, tested and owned. For the outbound side, where APIM authenticates to backends, see Azure API Management managed identity troubleshooting and API Management Key Vault certificates.
Last reviewed: October 2026
Sources
- validate-azure-ad-token policy (Microsoft Learn)
- validate-jwt policy (Microsoft Learn)
- Protect an API using OAuth 2.0 and Microsoft Entra ID (Microsoft Learn)
- Policies in Azure API Management (Microsoft Learn)
- Debug APIs using request tracing (Microsoft Learn)
Discover more from Cloud Osprey
Subscribe to get the latest posts sent to your email.