Install
$ agentstack add mcp-ozgurkarahan-propagate-id-entra ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Propagate ID Entra
End-to-end identity propagation from browser through AI agents to backend APIs — no service accounts in the data path.
[](https://learn.microsoft.com/azure/developer/azure-developer-cli/) [](https://www.python.org/) [](https://learn.microsoft.com/azure/azure-resource-manager/bicep/) [](LICENSE)
> A proof-of-concept showing how a user's Entra ID token can flow from a browser, through an AI Foundry agent with MCP tools, through API Management, all the way to a backend API — preserving the caller's identity at every hop. Deployed with a single azd up.
> 📖 Identity Propagation series — this repo is part of a series on end-to-end user identity propagation for AI agents: no service accounts in the data path, every action traceable to a real user. Read the story: From Theory to Production: Salesforce Meta-Tool & Identity Propagation. Companion repos: snow-meta-tool · salesforce-meta-tool-identity-propagation
Why identity propagation matters
Most AI agent integrations take a shortcut: the agent authenticates to backend systems with a shared service account. It works in a demo, but it means every order lookup, every record update, every API call lands in the audit log as the same technical user — regardless of who actually asked. The moment an agent can act on business systems, "who did this?" must have a real answer.
The service-account pattern also forces over-provisioning. Because one credential has to cover anything any user might do, it accumulates the union of everyone's permissions — a single high-value target that bypasses the per-user authorization your backends already enforce. And when auditors ask you to trace an AI-initiated action back to a person, a shared credential has nothing to offer.
Identity propagation flips this: the user's own Entra ID token travels with the request through every hop — browser, chat app, Foundry agent, APIM, backend API. Each layer validates the same delegated identity, the backend authorizes against the actual caller, and the audit trail names a human, not a bot.
| | Service-account pattern | Identity propagation (this repo) | |---|---|---| | Audit trail | Every action logged as the shared account | Every action traceable to the signed-in user | | Least privilege | One credential with the union of all users' permissions | Each request carries only that user's permissions | | Per-user authorization | Reimplemented (or skipped) in middleware | Enforced by the backend, per caller, at every hop | | Compliance | Hard to satisfy SOX/GDPR/ISO traceability requirements | Individual accountability built into the data path |
Architecture
flowchart TD
Browser["Browser(MSAL.js SPA)"]
Entra["Entra ID"]
ChatApp["Chat App(FastAPI + Container App)"]
Agent["AI Foundry Agent(gpt-4o)"]
APIM["API Management"]
MCP["/orders-mcpvalidate-jwt"]
REST["/orders-api"]
OAI["/openaiAI Gateway"]
Orders["Orders API(FastAPI + Container App)"]
AOI["Azure OpenAI"]
Browser -- "1 Sign in" --> Entra
Entra -- "access token" --> Browser
Browser -- "2 POST /api/chat{message, token}" --> ChatApp
ChatApp -- "3 Responses API(UserTokenCredential)" --> Agent
Agent -- "4 MCP tool call(UserEntraToken)" --> APIM
APIM --- MCP
APIM --- REST
APIM --- OAI
MCP --> Orders
REST --> Orders
OAI -- "Managed Identity" --> AOI
How Identity Flows
sequenceDiagram
participant B as Browser
participant E as Entra ID
participant C as Chat App
participant F as Foundry Agent
participant A as APIM
participant O as Orders API
B->>E: Sign in (MSAL.js)
E-->>B: Access token (aud=ai.azure.com)
B->>C: POST /api/chat {message, access_token}
Note over C: Wraps token inUserTokenCredential
C->>F: responses.create()
Note over F: Agent decides tocall MCP tool
F->>A: MCP request + Bearer token(UserEntraToken passthrough)
Note over A: validate-jwt(aud, issuer, signature)
A->>O: Forward request + JWT claims
O-->>A: Order data
A-->>F: MCP response
F-->>C: Agent response
C-->>B: Chat reply
| Hop | Auth Type | User Identity Preserved? | |-----|-----------|--------------------------| | Browser → Chat App → Foundry | Delegated (MSAL.js access token) | Yes | | Foundry → APIM MCP | UserEntraToken passthrough | Yes | | APIM → Azure OpenAI | Managed Identity (service-to-service) | No |
> [!IMPORTANT] > No OAuth2 client credentials, no consent prompts, no client secrets, no refresh token expiry. The user's existing Entra token is passed directly at every hop via a UserEntraToken connection.
Quick Start
> [!TIP] > azd up does everything: provisions Azure resources via Bicep, builds and deploys containers to ACR, then runs a post-provision hook to create the Entra app registration and Foundry agent.
Prerequisites
- Azure subscription with Owner/Contributor access
- Azure CLI (
az) — logged in - Azure Developer CLI (
azd) - Python 3.9+
- Git
Docker is not required locally — container builds run remotely on ACR.
Deploy
git clone https://github.com/ozgurkarahan/propagate-id-entra.git
cd propagate-id-entra
azd env new propagate-id-entra
azd up
Verify
python scripts/verify_deployment.py
python scripts/test-agent.py
What azd up Does
flowchart LR
P["azd provision"]
D["azd deploy"]
H["postprovision hook"]
P -- "Bicep modules(13 modules, 4 tiers)" --> D
D -- "Build + deployOrders API & Chat App" --> H
H -- "1. Entra app registration2. Foundry agent creation3. Chat App env vars" --> Done["Ready"]
Project Structure
Click to expand
| Path | Description | |------|-------------| | infra/main.bicep | Subscription-scoped Bicep orchestrator | | infra/modules/ | 13 Bicep modules (APIM, Cognitive, Container Apps, etc.) | | infra/policies/ | APIM policies (JWT validation, AI Gateway, RFC 9728 PRM) | | src/orders-api/ | FastAPI Orders CRUD backend (6 endpoints, 8 seed orders) | | src/chat-app/ | FastAPI backend + vanilla JS SPA with MSAL.js | | hooks/postprovision.py | Entra app registration + Foundry agent creation | | scripts/ | Deployment verification, diagnostics, agent testing | | docs/ | Deep-dive architecture, identity & security, reference docs |
Learn More
- [Identity & Security Architecture](docs/identity-security.md) — Entra app registration, managed identities, JWT validation, RFC 9728, security design decisions
- [Deep Dive](docs/deep-dive.md) — ARM resource details, data flows, step-by-step build guide
- [AGENT.md](AGENT.md) — Architecture diagrams, auth flow details, IaC principles, development reference
License
[MIT](LICENSE)
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: ozgurkarahan
- Source: ozgurkarahan/propagate-id-entra
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.