An Azure service that provides a hybrid, multi-cloud management platform for APIs.
Azure API Management MCP server: 401 after OAuth sign-in when the identity tenant is Azure AD B2C (same setup works with Entra ID P2 tenant)
Service
Azure API Management (Expose REST API as MCP Server), Azure AD B2C, Microsoft Entra ID, Azure Functions backend. The MCP Host is Claude Desktop, using a custom connector.
Scenario
We use a two-tenant setup. One tenant hosts our resources, and our users live in a separate tenant. We exposed an existing REST API as an MCP server through APIM, secured with OAuth 2.1 (authorization code + PKCE, public client, no secret).
This setup works end to end when the user tenant is a Microsoft Entra ID tenant (P2 licensed). We are now trying the same setup with an Azure AD B2C tenant as the user tenant, and it fails.
The APIM inbound policy on the MCP server does three things:
- If a request has no
Authorizationheader, it returns 401 withWWW-Authenticate: Bearerso the MCP client starts the OAuth flow. - If a request has
Authorization: Bearer <token>, it validates the token's signature, issuer and audience against the user tenant usingvalidate-azure-ad-tokenwithtenant-id. - If validation succeeds, it forwards the request unchanged to the tools.
Result
With the Entra ID user tenant, sign-in completes and MCP calls succeed.
With the Azure AD B2C user tenant, the browser completes sign-in and shows a success page. After that, the Claude Desktop shows Server returned 401 Unauthorized on re-authentication. From our side we can't tell which of these is happening:
- (a) The authorization code to token exchange at the B2C
/tokenendpoint failed silently after the browser showed success, so no token was issued and the client retried without one, or - (b) A token was issued but our APIM policy rejected it, for example because of the wrong audience, issuer or signing key.
Environment
- Tenant A (resource tenant, Microsoft Entra ID): APIM instance, MCP server, backend Function App
- Tenant B (user tenant): previously a Microsoft Entra ID P2 tenant (working); now an Azure AD B2C tenant (failing)
- App registration live in the user tenant
- APIM tier: [Basic v2]
- Token version: [v2]
Supporting materials
Sanitized inbound policy:
<policies>
<inbound>
<choose>
<when condition="@(!context.Request.Headers.ContainsKey("Authorization"))">
<return-response>
<set-status code="401" reason="Unauthorized" />
<set-header name="WWW-Authenticate" exists-action="override">
<value>Bearer</value>
</set-header>
</return-response>
</when>
</choose>
<validate-azure-ad-token tenant-id="<b2c-tenant-id>" header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid.">
<client-application-ids>
<application-id><app-client-id></application-id>
</client-application-ids>
<audiences>
<audience><app-client-id></audience>
<audience>https://verified-domain/<app-client-id></audience> # This was api://<app-client-id> in P2 Setup
</audiences>
</validate-azure-ad-token>
<base />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
Question
When OAuth sign-in against Azure AD B2C looks successful in the browser but the client then gets a 401 from APIM, what is the recommended way to find out whether the failure happened at the B2C /token exchange or in the APIM validation policy, given that the same policy works with an Entra ID user tenant?