I have spent several days on this. Following articles such as:
https://learn.microsoft.com/en-us/azure/ai-foundry/agents/how-to/tools/openapi?view=foundry&preserve-view=true&pivots=csharp#authenticate-by-using-managed-identity-microsoft-entra-id
I have an Api 421xxxxxxxxxxxx deployed that has an AppRole named 'AppOnlyRole' which I have assigned to the Service Principal bbbxxxxxxxxxxxx which is the Foundry System-assigned Managed Identity. I have also created a Federated Credential for that Managed Identity on the Api AppReg 421xxxxxxxxxxxxxxxx
I have confirmed the API works by invoking it from a React client.
The Agent's Open API Tool Audience is set to 421xxxxxxxxxxxxxxxx
It is not api://421xxxxxxxxxxxxxxx or api://421xxxxxxxxxxxxxx/AppOnlyRole.
I have used New-MgServicePrincipalAppRoleAssignment to assign the AppOnlyRole to the Foundry Managed Identity, and I see it on the Enterprise App Security blade confirming it is assigned.
Using the Agent Playground, I send a message "get user info" and the agent correctly finds the Open API Endpoint and invokes it with an access token. The agent responds with this error:
Error{ "error": "Validation Error", "message": "('HTTP error 401: Unauthorized', 'http_client_error', {'curl': "curl -X GET 'https://mike-ai-crudtool-yrmg5np.azurewebsites.net/api/tasks/GetUserInfo?REDACTED' -H 'Content-Type: REDACTED' -H 'Accept: REDACTED' -H 'Authorization: REDACTED'"})", "func_call_name": "GetUserInfo", "spec_id": "MikeTestApiAuth", "type": "ValidationError", "debug_info": { "error_type": "validation_error", "tool_name": "python_openapi_tool_MikeTestApiAuth", "curl_command": "curl -X GET 'https://mike-ai-crudtool-yrmg5np.azurewebsites.net/api/tasks/GetUserInfo?REDACTED' -H 'Content-Type: REDACTED' -H 'Accept: REDACTED' -H 'Authorization: REDACTED'" } }
My API logs the access token to the console, and I can see the Application Identity claim value is the Foundry Managed Identity App Id. The token passes validation:
IDX10234: Audience Validated.Audience: '421xxxxxxxxxxxxxxxxxxxxxx'
but user?.Identity?.IsAuthenticated is false. There are no scp or role claims in the token.
The Controller is not demanding a scope, it simply has the attribute [Authorize]
The API configuration for MS Identity is:
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(jwtOptions =>
{
jwtOptions.Authority = "https://login.microsoftonline.com/97d1fbxxxxxxxxxxxxxxxx";
jwtOptions.Audience = "421xxxxxxxxxxxxxxxxxxxxx";
jwtOptions.TokenValidationParameters.ValidAudiences = new[]
{
"api://421xxxxxxxxxxxxxxxxxxx", // v2-style audience
"421xxxxxxxxxxxxxxxxxxxxx" // bare GUID (v1-style MI token)
};
jwtOptions.TokenValidationParameters.ValidIssuers = new[]
{
// v1 issuer
"https://sts.windows.net/97dxxxxxxxxxxxxxxxxxxx/",
// v2 issuer
"https://login.microsoftonline.com/97dxxxxxxxxxxxxxxxxxxxxxx/v2.0",
// some libraries still emit this form
"https://login.microsoftonline.com/97dxxxxxxxxxxxxxxxxxxxxxx/"
};
},
identityOptions =>
{
identityOptions.Instance = "https://login.microsoftonline.com/";
identityOptions.TenantId = "97dxxxxxxxxxxxxxxxx";
identityOptions.ClientId = "421xxxxxxxxxxxxxxxxxxxxxxxxxe";
});
builder.Services.AddAuthorization();