Chapter 5 of 6
Implement#
1. Prepare Foundry and the approved network path#
In Foundry, confirm that each selected Claude deployment is Succeeded. Record its deployment name, hosting option, and model version in the approved change record. Test a small Messages request through the platform owner's existing Entra-authorized path before configuring APIM.
Enable APIM's system-assigned managed identity if it is not already enabled. In Foundry Access control (IAM), grant that identity Cognitive Services User on the resource. Allow role propagation before diagnosing a failed backend call. Developers do not need their own Foundry role for this route.
If using Application Gateway WAF, use an approved WAF_v2 listener and TLS certificate. Route to APIM with the correct backend hostname, preserve the API suffix, and confirm probe health. Restrict APIM to that gateway using the approved private path or an IP filter with the gateway's observed egress IP. An unrestricted public APIM endpoint bypasses WAF inspection even though the API's identity and budget policy still applies.
Start WAF rule tuning in Detection mode with representative non-sensitive code prompts. Check body-inspection limits and oversized-body behavior. Use narrow, logged exclusions for demonstrated false positives before Prevention mode. WAF is not a model safety filter and does not inspect streamed responses as a prompt/response moderation service.
2. Configure the two Entra applications#
Create a single-tenant Gateway API registration. Set Application ID URI to api://<gateway-api-client-id>, expose admin-consented delegated scope AiGateway.Invoke, and preauthorize Microsoft Azure CLI client 04b07795-8ddb-461a-bbee-02f9e1bf7b46 for that scope. Define app role Gateway.Invoke for Users/Groups. On the Enterprise application, enable Assignment required and assign approved users or groups to that role. The identity owner grants the delegated consent required by the tenant; a noninteractive token helper cannot complete consent.
Create a separate single-tenant Claude Desktop Gateway public-client registration. Under Mobile and desktop applications, add exactly http://127.0.0.1/callback, with no fixed port. Create no secret or certificate. Add optional ID-token claim upn, define Users/Groups app role Gateway.Invoke, enable Assignment required, and assign the approved cohort to that role.
Inspect token claims locally without sending tokens to a web decoder or retaining them. Confirm the following contract before setting identityApproved.
| Claim | Code access token | Desktop ID token |
|---|---|---|
iss | https://sts.windows.net/<tenant-id>/ | https://login.microsoftonline.com/<tenant-id>/v2.0 |
aud | api://<gateway-api-client-id> | Bare Desktop client ID |
tid | Approved tenant ID | Same tenant ID |
roles | Contains Gateway.Invoke | Contains Gateway.Invoke |
upn | Nonempty user UPN | Nonempty optional user UPN |
APIM's Developer Portal OAuth configuration does not establish this trust. The two validate-jwt branches in the API policy establish it.
3. Complete the files and run preflight#
In the customer copies, replace the tenant and app IDs in the policy and both helpers. Set Code's base URL to the approved route including its API suffix. Map each default model alias to an exact lowercase Foundry deployment name. Set the same names in the budget fragment and approve the token allowances. Add normalized UPN overrides when needed, using model-to-integer JSON objects.
Set apiKeyHelper to the installed command: an executable Bash helper on macOS/Linux, or pwsh -NoProfile -File followed by the quoted installed PowerShell helper path on Windows. Preserve unrelated device settings when merging the supplied JSON.
From this module's implementation directory, pass the customer copy's artifact directory directly to preflight:
PowerShell
.\scripts\preflight.ps1 -ArtifactsDir "C:\approved-work\claude-gateway"
Bash
bash scripts/preflight.sh --artifacts-dir "$HOME/approved-work/claude-gateway"
Preflight rejects unresolved decisions, unapproved flags, a different active Azure subscription or tenant, a classic APIM tier, a missing managed identity, a missing Foundry resource role, and missing deployments. It checks file syntax and alignment, not APIM's C# policy compilation.
Portal policy edits have no ARM what-if preview. Before saving, the gateway owner reviews the exact change against the stored prior policy and uses the portal's effective-policy view to inspect inherited controls. The supplied backend section sets one nonbuffering forward-request instead of inheriting another forwarding policy. Retain any required inherited backend behavior explicitly, without introducing a second forward.
4. Configure APIM#
Create backend claude-foundry-backend, protocol HTTPS, with runtime URL https://<foundry-resource>.services.ai.azure.com/anthropic. Create a Language Model API / passthrough API, not an OpenAI-compatible API. Use API suffix foundry or the suffix already approved in the base URL. Disable Subscription required. A product can group the API, but must not be the identity or budget authority.
Expose POST /v1/messages and POST /v1/messages/count_tokens. If the wizard created wildcard operations, remove them and add these two explicit POST operations with the same paths. Do not open unrelated endpoints. The ?beta=true query on Messages must still route normally. Desktop model discovery is configured explicitly, so this route does not require GET /v1/models; Code's optional HEAD /api/hello probe can return 404.
Under Policy fragments, import the customer copy of budget-fragment.xml as claude-foundry-budgets. Apply the customer copy of api-policy.xml at API / All operations scope. Save only after the portal accepts its policy expressions. The included fragment supplies budgets for every API call regardless of product context.
Review the full inherited policy. Keep anthropic-version and anthropic-beta unchanged, preserve new Anthropic headers and all body fields, including cache_control. Remove transformations that reconstruct Messages bodies or strip unfamiliar beta values. preserveContent: true lets the policy read the model without consuming the request body.
The token and metric policies run on Messages, not on count_tokens. Both operations still require an authorized identity and a positive model budget. The backend forward-request disables response buffering. Keep SSE events, including pings and final usage events, in order through every proxy.
Configure an approved Application Insights logger and API diagnostics. Set request and response body logging to 0 bytes and diagnostic verbosity to information for the identity trace. Do not log Authorization, x-api-key, cookies, or subscription keys. UPN and object ID are personal data: approve access and retention. Token metrics are operational estimates; do not treat them as the invoice.
Enable Application Insights custom metrics with dimensions for the token policy. APIM limits each dimension to 100 unique values and each namespace to 1,000 active time series; new values beyond those limits are discarded. The per-user metric is suitable for a bounded pilot. Before a larger rollout, use a bounded metric dimension and an approved attribution pipeline rather than treating the UPN metric as a complete chargeback record.
5. Connect Claude Code#
Install the configured helper with the device's normal managed-file permissions. Merge the configured settings into the approved Claude Code configuration. The helper prints only a token to stdout and sends errors to stderr. It retries once after interactive sign-in to the configured tenant.
Remove conflicting ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, and direct Foundry/provider-mode variables from the managed configuration and launch environment. This is the generic Messages gateway path selected by ANTHROPIC_BASE_URL, not direct Foundry mode.
Start Code and inspect /status: the API base URL must be the gateway. Confirm /model resolves to the managed deployment names. Reopen the client after changing settings. If the token helper needs initial consent or browser sign-in, complete it interactively before unattended use.
6. Connect Claude Desktop#
Follow Desktop's gateway configuration for the installed supported build. Open Developer / Configure Third-Party Inference and set:
| Setting | Value |
|---|---|
| Inference provider | Gateway |
| Gateway base URL | Same approved URL as Code, including /foundry |
| Credential kind | Interactive sign-in |
| Gateway auth scheme | Bearer |
| OIDC client ID | Desktop public-client ID |
| OIDC issuer URL | https://login.microsoftonline.com/<tenant-id>/v2.0 |
| OIDC scopes | Leave unset to use the documented defaults including offline_access |
| Redirect port | Leave unset |
| Models | Explicit approved Foundry deployment names |
Use the configuration window's Export command for the MDM .mobileconfig or .reg payload. The profile needs both inferenceCredentialKind: "interactive" and inferenceGatewayOidc. In MDM, the latter is a JSON-encoded string; do not recreate it as nested plist or registry keys. If scopes are set explicitly with the default ID-token mode, include offline_access to support silent refresh. Distribute the profile through the approved device-management path and restart Desktop.