Skip to content

.NET: Preserve toolbox OAuth consent context - #9565

Merged
Roger Barreto (rogerbarreto) merged 3 commits into
microsoft:mainfrom
rogerbarreto:consent-request-context
Oct 22, 2026
Merged

Roger Barreto (rogerbarreto) merged 3 commits into
microsoft:mainfrom
rogerbarreto:consent-request-context

Conversation

@rogerbarreto

Copy link
Copy Markdown
Member

Motivation & Context

Hosted agents can lose an OAuth consent request after streaming a tool-call event. When the toolbox returns JSON-RPC -32006, the consent wrapper no longer sees the request's consent state, so the error reaches the model as Error: Function failed. instead of reaching the caller as an oauth_consent_request.

Even when the state is available, using the MCP exception's entire formatted message as the consent URL causes the existing URL policy to reject an otherwise valid link.

Description & Review Guide

  • What are the major changes? Bind the same request-owned consent state while advancing and disposing the agent stream, restoring the previous value in finally. Read the consent URL from structured error details, with an exact SDK-prefix fallback only when the detail field is absent. Add regressions using the real MCP client and function-execution loop, including concurrent requests, invalid details, and early stream disposal.
  • What is the impact of these changes? Consent requests survive streaming without sharing state between requests or replacing the caller's context. HTTPS and optional allowed-origin checks remain enforced. Public APIs, response-status behavior, and the existing cancellation strategy are unchanged. A live hosted comparison with tool search and a read-only OAuth OpenAPI tool reproduced the generic failure on the published package and returned the consent item with this fix. The saved response retained it, and streaming and non-streaming clients recovered it through AIContent.RawRepresentation. Completing OAuth authorization and verifying callback identity binding were not part of that comparison.
  • What do you want reviewers to focus on? Request-context lifetime across iterator suspension and disposal, preserving the caller's prior context, and rejecting malformed structured details rather than silently using a different URL from the error message.

Related Issue

Refs #8379, specifically the missing consent response reported in this reproduction.

This PR deliberately does not close #8379 because the original report also concerns OAuth callback identity binding, which this change does not establish as fixed. No competing open PR was found. The issue remains in triage without a public implementation-approval label or comment.

AI Assistance

  • No material AI assistance was used.
  • This is an AI-assisted contribution. I reviewed, understood, and verified all submitted content and accept responsibility for it.

AI assistance details: Copilot assisted with diagnosis, implementation, regression tests, live reproduction, and this PR description.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR links to an agreed issue with no competing open PR, or the Related Issue section documents a trivial-change or repository-automation exception.
  • This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after a language prefix) and the workflows keep the label and title prefix in sync automatically.

Bind request consent state across stream advances and disposal.
Extract the actual consent URL without bypassing link validation.

Refs microsoft#8379
Copilot AI balanced review requested due to automatic review settings October 20, 2026 18:44
@agent-framework-automation agent-framework-automation Bot added the .NET Usage: [Issues, PRs], Target: .Net label Oct 20, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

Static review identified no blocking issues in the focused changes or regression coverage; tests were not executed during review.

No open issues 🎉

What changed in this PR

Preserves OAuth consent requests during hosted .NET agent streaming. This addresses missing consent responses from #8379, not callback identity binding.

Changes:

  • Bind request-owned consent state during stream advancement and disposal, restoring the previous context afterward.
  • Extract consent URLs from structured error details, falling back to the message only when details are absent.
  • Add regressions for real MCP tool invocation, concurrent requests, malformed details, and early disposal.
File Description
dotnet/​tests/​Microsoft.Agents.AI.Foundry.Hosting.UnitTests/​OAuthConsentToolInvocationTests.cs Adds MCP consent propagation and isolation regressions.
dotnet/​tests/​Microsoft.Agents.AI.Foundry.Hosting.UnitTests/​OAuthConsentPolicyHandlerTests.cs Tests context preservation during early disposal.
dotnet/​src/​Microsoft.Agents.AI.Foundry.Hosting/​McpConsentContext.cs Clarifies context lifetime documentation.
dotnet/​src/​Microsoft.Agents.AI.Foundry.Hosting/​ConsentAwareMcpClientAIFunction.cs Extracts consent URLs and corrects output-item documentation.
dotnet/​src/​Microsoft.Agents.AI.Foundry.Hosting/​AgentFrameworkResponseHandler.cs Scopes consent context around stream advancement and disposal.

Review effort: Balanced

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAF Automated Review — Iteration 1

Result: No findings
Scope: full PR (1 commit(s)): be1d3a22f09d
Model: gpt-5.6-sol

Overview

The change preserves request-owned OAuth consent state across async stream advancement and disposal, restores prior ambient state in finally, and prefers structured MCP error details with a constrained legacy fallback. Concurrent-request, malformed-detail, URL-policy, persistence, and early-disposal tests provide strong coverage, and no publishable Critical, High, or Medium defect remained after reconciliation.

Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
No publishable findings remained after source verification for this scope.

@rogerbarreto
Roger Barreto (rogerbarreto) added this pull request to the merge queue Oct 21, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to no response for status checks Oct 21, 2026
@rogerbarreto
Roger Barreto (rogerbarreto) added this pull request to the merge queue Oct 21, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to no response for status checks Oct 21, 2026
@rogerbarreto
Roger Barreto (rogerbarreto) added this pull request to the merge queue Oct 22, 2026
Merged via the queue into microsoft:main with commit ce214c0 Oct 22, 2026
32 checks passed
@rogerbarreto
Roger Barreto (rogerbarreto) deleted the consent-request-context branch October 22, 2026 14:23

This branch was successfully deployed

1 active deployment
github-app-auth — 8d13a8d6 Deployed Oct 22, 2026 by rogerbarreto via add_label #25934
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

.NET Usage: [Issues, PRs], Target: .Net

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.NET: [Bug]: Hosted agent toolbox consent link is bound to the container's managed identity, so sign-in fails with "Code <id> not found"

4 participants