APIM + Entra ID JWT Authentication Setup
This guide provides a step-by-step configuration for protecting your API in Azure API Management (APIM) using Microsoft Entra ID (Azure AD) application tokens (client credentials flow).
1. Prerequisites
- Azure API Management (APIM) instance
- Backend API (App Service, Function, Container App, etc.)
- Microsoft Entra ID tenant
- Admin access to APIM and Entra ID
2. Register API App in Entra ID
- Register a new app (your API)
- Add ownership to your Entra ID tenant
- Expose an API: set Application ID URI (e.g.,
api://{API_APP_ID_URI}) - Add scope name: e.g:
access - Who can consent: Admins only
- Admin consent display name:
access - Admin consent description:
Access to the API - Save (other fields optional)
- Add a client application (the caller app) in "Authorized client applications" with its Application (client) ID
- This should be the app registered in step 3.
- Add App Role:
access(for Applications) - Allowed member types: Applications
- Value:
access - Description:
Allows access to the API - Name must be unique within the entire tenant. (e.g.,
PROD-RCV-Chat-Access)
3. Register Client App in Entra ID
- Register a new app (the client/caller)
- Create a client secret
- Add API permission: Application permission
accessto your API app - Grant admin consent
4. APIM Policy for JWT Validation
Paste this in your API's Inbound policy (adjust placeholders):
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" require-scheme="Bearer">
<openid-config url="https://login.microsoftonline.com/{TENANT_ID}/v2.0/.well-known/openid-configuration" />
<audiences>
<audience>api://{API_APP_ID_URI}</audience>
<audience>{API_APP_CLIENT_ID}</audience>
</audiences>
<required-claims>
<claim name="roles" match="any">
<value>Api.Access</value>
</claim>
</required-claims>
</validate-jwt>
5. Getting a Token (Client Credentials)
POST to:
https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token
Body (x-www-form-urlencoded):
grant_type=client_credentials
client_id={CLIENT-APP-ID}
client_secret={CLIENT-APP-SECRET}
scope=api://{API_APP_ID_URI}/.default
6. Calling the API
Send both headers:
Authorization: Bearer <access_token>
Ocp-Apim-Subscription-Key: <subscription-key>
7. Troubleshooting
- 401: Check
aud,roles, andissclaims in the token - Use
/.defaultscope for client credentials - Ensure APIM policy matches your setup
For a full, detailed guide (with PowerShell/cURL examples, onboarding bundle, and troubleshooting), see: docs/security/APIM-EntraID-JWT-Setup.md