microsoft / microsoft/mcp

On-Behalf-Of (OBO) outgoing auth strategy does not support service principal or managed identity callers

Open
#2,192 1 comment 0 reactions 1 assignee View on GitHub

@vukelich is already working on this.

Since Mar 24, 2026.

remote-mcp server-Azure.Mcp
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.