How the Microsoft Entra Agent ID sidecar lets an AI agent call downstream APIs with a secure, per-agent identity — without the agent code ever seeing a secret.
For runnable samples, see:
dev/— local-LLM (Ollama) editionaws/— AWS Bedrock (Claude) editionweather-api/— shared downstream API used by both
For the PowerShell bootstrap that creates the Entra objects used by every sample, see ../scripts/README.md.
Tip
Deploying these samples to Azure? Use the AI-assisted skills for a faster, less error-prone path than running every command by hand: deploy-agent-aca-dev (local-LLM on ACA) and deploy-agent-aca-aws (AWS Bedrock on ACA). Each skill works with Claude Code and GitHub Copilot Chat and typically cuts a multi-hour manual deploy down to minutes.
Two common approaches to agent authentication both fall short:
- Hard-coded secrets in agent code. Every agent image holds a copy of your app's
client_secret. Any compromise, any log leak, any forgotten.envcommitted to Git is a full tenant breach. - Delegated user tokens for everything. The agent is reduced to acting only when a human is present, and you lose individual auditability — every call looks like the same service principal.
Entra Agent ID gives each agent its own identity. The sidecar pattern makes that identity easy to use.
The Microsoft Entra SDK auth sidecar (mcr.microsoft.com/entra-sdk/auth-sidecar) runs as a second container next to your agent. It exposes a small HTTP API on the pod-local network and handles:
- Client-credentials exchange with
login.microsoftonline.com - Client-credentials or federated identity credential (FIC) token acquisition for the Agent Identity (autonomous flow)
- On-Behalf-Of (OBO) flows for user-context calls
- Token caching, refresh, and expiry
- Credential source abstraction —
ClientSecretfor dev,SignedAssertionFromManagedIdentityfor Azure deployments, same API
Your agent asks the sidecar "give me an authorization header for this API" and gets back Bearer eyJ…. Credentials never live in agent memory.
| Agent (your code) | Sidecar (Microsoft Entra SDK) |
|---|---|
| Decide when to call the API | Acquire and cache the right token |
| Build the HTTP request | Perform client-credentials and OBO exchange |
| Pass through user token for OBO | Validate and forward user assertion |
| Handle business logic | Talk to login.microsoftonline.com |
The security boundary is explicit: the sidecar has no host port. Only services inside the same network (your agent, not your browser, not random processes on the host) can request tokens.
| Object | Role | Where it lives |
|---|---|---|
| Blueprint application | Factory / template that issues Agent Identities. Holds the client credential (secret or federated). | Your Entra tenant |
| Agent Identity | The individual AI agent. Has its own app ID, its own permission grants (e.g. User.Read.All), its own audit trail. |
Your Entra tenant |
| Client SPA (OBO only) | Web UI that signs the user in and exchanges the user's token into an Agent token on their behalf. | Your Entra tenant |
| Sidecar container | Runs client-credentials and OBO flows. Knows the Blueprint credential. | Next to your agent |
| Agent container | Your application code. Asks the sidecar for headers. | Your pod / compose / App Service |
Provisioning is covered in ../scripts/README.md — the Start-EntraAgentIDWorkflow PowerShell cmdlet creates all three Entra objects in one shot.
- The difference between a Blueprint and an Agent Identity, and why agents need their own identity.
- How the sidecar exposes
/AuthorizationHeader(get token) and/DownstreamApi(token + proxied call) endpoints. - How to forward a signed-in user's token to the agent and have the Microsoft Entra SDK for Agent ID mint an agent-on-behalf-of-user token via OBO.
- How the downstream API validates agent tokens cryptographically — signature, issuer,
xms_par_app_azp, audience. - How to swap from
ClientSecret(dev) toSignedAssertionFromManagedIdentity(Azure deployments) without changing a line of agent code.
| To… | Go to |
|---|---|
| Set up Blueprint + Agent Identity in your Entra tenant | ../scripts/README.md |
| Run a local-LLM demo in five minutes | dev/README.md |
| Run the same demo against AWS Bedrock | aws/README.md |
| Deploy to Azure Container Apps (no stored secrets) | ../deploy/azure/container-apps/ |