On-Behalf-Of (OBO) outgoing auth strategy does not support service principal or managed identity callers
@vukelich is already working on this.
Since Mar 24, 2026.
- Dominant language
- C#
- Stars
- 3.7k
- Forks
- 624
- Avg merge
- 2d 20h
- Merged PRs (30d)
- 220
Description
## Summary
When the Azure MCP Server is deployed remotely with `--outgoing-auth-strategy UseOnBehalfOf`, callers that authenticate using **application-only tokens** (service principals, managed identities, or any client using the [client credentials flow](https://learn.microsoft.com/entra/identity-platform/v2-oauth2-client-creds-grant-flow)) will fail when the server attempts to call downstream Azure services.
This is a **Microsoft Entra ID platform limitation** — the [OBO flow](https://learn.microsoft.com/entra/identity-platform/v2-oauth2-on-behalf-of-flow) requires a **user assertion** (a token with user context). App-only tokens cannot be used as OBO assertions.
## Error
When a service principal or managed identity calls the Azure MCP Server running with `UseOnBehalfOf`, downstream Azure service calls fail with:
```
AADSTS7000114: Application '' is not allowed to make application on-behalf-of calls.
```
The MSAL team has confirmed this is not a supported flow ([AzureAD/microsoft-authentication-library-for-dotnet#2130](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/2130)).
## Who is affected?
Any deployment where the MCP client authenticates as an application rather than a user, including:
- **AI agents** running as service principals (e.g., Foundry agents, GitHub Coding Agent)
- **Managed identities** calling the MCP server from another Azure service
- **Daemon applications** using client credentials flow
- **Automated pipelines** authenticating with client secrets or certificates
## Workaround
### Agent ID Blueprints in Entra (emerging)
[Agent ID Blueprints](https://learn.microsoft.com/entra/identity/agents/agent-id-blueprint-overview) are a new Entra concept that allows agents to act as user principals rather than service principals. Because the resulting token carries user context, it should be compatible with the OBO flow — meaning per-user RBAC and audit trails are preserved.
> [!NOTE]
>
> This is an emerging capability. We have not yet fully validated the end-to-end flow with Azure MCP Server. If you have success or issues using Agent ID Blueprints with `UseOnBehalfOf`, please share your experience in this issue.
### What about `UseHostingEnvironmentIdentity`?
Switching to `--outgoing-auth-strategy UseHostingEnvironmentIdentity` will avoid the OBO error, but it is **not recommended as a general workaround**. With this strategy, all callers share the server's managed identity and its full set of permissions — effectively granting every caller elevated, uniform access to downstream Azure services. This defeats the per-user RBAC and audit trail benefits that OBO is designed to provide.
## What happens
```mermaid
sequenceDiagram
participant Agent as Agent / Daemon / Pipeline
(service principal)
participant Entra1 as Entra ID
participant MCP as Azure MCP Server
(UseOnBehalfOf)
participant Entra2 as Entra ID
participant Azure as Downstream Azure Service
(Storage, ARM, etc.)
Agent->>Entra1: 1. Request token via client credentials flow
Entra1-->>Agent: App-only token (roles claim, no user context)
Agent->>MCP: 2. Call MCP tool with app-only bearer token
MCP->>MCP: 3. Validate inbound token ✅
MCP->>Entra2: 4. OBO token exchange (app-only assertion)
Entra2--xMCP: ❌ AADSTS7000114: Application is not allowed
to make application on-behalf-of calls
Note over MCP,Azure: Downstream call never happens —
token exchange is rejected by Entra ID
```
### Contrast: working flow with a user
```mermaid
sequenceDiagram
participant User as User / Interactive Client
participant Entra1 as Entra ID
participant MCP as Azure MCP Server
(UseOnBehalfOf)
participant Entra2 as Entra ID
participant Azure as Downstream Azure Service
User->>Entra1: 1. Sign in (authorization code flow)
Entra1-->>User: Delegated token (scp claim, user context)
User->>MCP: 2. Call MCP tool with delegated bearer token
MCP->>MCP: 3. Validate inbound token ✅
MCP->>Entra2: 4. OBO token exchange (user assertion)
Entra2-->>MCP: ✅ New token scoped for downstream service
MCP->>Azure: 5. Call Azure service with exchanged token
Azure-->>MCP: 6. Response (user's RBAC permissions apply)
```
## Root cause
The Entra ID OBO flow is designed to propagate **delegated user identity** through a service chain. It validates that the incoming assertion contains a user principal (`scp` claim from delegated permissions). App-only tokens contain `roles` claims instead of `scp` claims and are rejected by the token exchange endpoint.
This limitation is documented in the [Entra OBO flow documentation](https://learn.microsoft.com/entra/identity-platform/v2-oauth2-on-behalf-of-flow) and confirmed by the MSAL team. There is a [community feature request](https://feedback.azure.com/d365community/idea/ddcad714-c725-ec11-b6e6-000d3a4f0789) for Entra to support service-principal-to-service-principal OBO.
## What would fix this?
This is not something the Azure MCP Server can fix independently. It requires upstream changes in Microsoft Entra ID to support app-only OBO token exchange. If Entra adds this capability in the future, the Azure MCP Server can adopt it.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.