Use MSAL's recent UserFIC API for agentic flows#3842
Merged
Conversation
Replace ROPC piggybacking with MSAL's native AcquireTokenByUserFederatedIdentityCredential API using the multi-CCA pattern (blueprint + per-agent CCAs with assertion callbacks). This enables proper token caching for agentic User FIC flows when ClaimsPrincipal is null, eliminating 2-4 unnecessary network round-trips per bot message. Phase 1: UPN-based flows only. OID-based flows remain on the existing ROPC+add-in path pending MSAL .NET support for the OID overload. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Avery-Dunn
marked this pull request as draft
June 4, 2026 20:04
- Bump MSAL .NET from 4.84.1 to 4.84.2 (adds Guid userObjectId overload for AcquireTokenByUserFederatedIdentityCredential) - Extend TryGetAuthenticationResultForAgentUserFicAsync to handle both UPN-based and OID-based agentic flows via native MSAL APIs - Remove AgentUserIdentityMsalAddIn (ROPC body-rewriting workaround) and its registration in AddAgentIdentities — no longer needed - Remove dead agent identity extraction code from ROPC path - Add 3 OID-specific tests: cache on second call, fresh ClaimsPrincipal per call, and UPN/OID cache isolation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR modernizes the agentic “User FIC” token acquisition flow by replacing the prior ROPC piggybacking/request-rewrite add-in with MSAL’s native AcquireTokenByUserFederatedIdentityCredential API, aiming to restore proper MSAL cache usage and fix the cache-bypass reported in #3840.
Changes:
- Bumps MSAL .NET to 4.84.2 and switches agentic user token acquisition to native UserFIC (multi-CCA / 3-leg flow).
- Adds internal caching structures for per-agent CCA instances and MSAL account identifiers to enable silent token acquisition even when
ClaimsPrincipalis null. - Removes the internal MSAL add-in that rewrote ROPC requests and adds new unit tests covering UPN/OID cache behavior.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| Directory.Build.props | Updates MSAL .NET version to enable the needed UserFIC overload. |
| src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs | Implements native UserFIC flow, agent CCA caching, and account-id mapping for silent cache hits. |
| src/Microsoft.Identity.Web.TokenAcquisition/Constants.cs | Adds an internal key for overriding the token-exchange audience via ExtraParameters. |
| src/Microsoft.Identity.Web.AgentIdentities/AgentIdentitiesExtension.cs | Stops registering the old ROPC-rewrite callback in AddAgentIdentities(). |
| src/Microsoft.Identity.Web.AgentIdentities/AgentUserIdentityMsalAddIn.cs | Deletes the internal add-in that rewrote token requests. |
| tests/Microsoft.Identity.Web.Test/TokenAcquisitionTests.cs | Adds new tests for agentic UserFIC caching behavior (UPN + OID). |
bgavrilMS
reviewed
Jun 5, 2026
Avery-Dunn
marked this pull request as ready for review
June 5, 2026 15:30
Replace ROPC piggybacking with MSAL's native AcquireTokenByUserFederatedIdentityCredential API using the multi-CCA pattern (blueprint + per-agent CCAs with assertion callbacks). This enables proper token caching for agentic User FIC flows when ClaimsPrincipal is null, eliminating 2-4 unnecessary network round-trips per bot message. Phase 1: UPN-based flows only. OID-based flows remain on the existing ROPC+add-in path pending MSAL .NET support for the OID overload. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Bump MSAL .NET from 4.84.1 to 4.84.2 (adds Guid userObjectId overload for AcquireTokenByUserFederatedIdentityCredential) - Extend TryGetAuthenticationResultForAgentUserFicAsync to handle both UPN-based and OID-based agentic flows via native MSAL APIs - Remove AgentUserIdentityMsalAddIn (ROPC body-rewriting workaround) and its registration in AddAgentIdentities — no longer needed - Remove dead agent identity extraction code from ROPC path - Add 3 OID-specific tests: cache on second call, fresh ClaimsPrincipal per call, and UPN/OID cache isolation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…AzureAD/microsoft-identity-web into avdunn/agentic-fic-scenario-fix
bgavrilMS
reviewed
Jun 17, 2026
bgavrilMS
reviewed
Jun 17, 2026
This was referenced Jul 20, 2026
Closed
Open
Merged
github-actions Bot
pushed a commit
to EelcoLos/nx-tinkering
that referenced
this pull request
Jul 21, 2026
Pinned [Microsoft.Identity.Web](https://github.com/AzureAD/microsoft-identity-web) at 4.13.2. <details> <summary>Release notes</summary> _Sourced from [Microsoft.Identity.Web's releases](https://github.com/AzureAD/microsoft-identity-web/releases)._ ## 4.13.2 ## What's Changed * Apply reserved-header handling on the request-clone path and cover all X-MS-TOKEN- headers by @iNinja in AzureAD/microsoft-identity-web#3915 * Restore independent PR pipeline + pool-aware MI identity + net462/472 unit tests by @iarekk in AzureAD/microsoft-identity-web#3935 * Post-release 4.13.0: changelog and public API shipped move by @neha-bhargava in AzureAD/microsoft-identity-web#3937 * Remove redundant 'Run unit tests' GitHub Action by @iarekk in AzureAD/microsoft-identity-web#3939 * Apply consistent redirect-URI validation on AccountController.SignIn by @iNinja in AzureAD/microsoft-identity-web#3940 * Fix duplicate logging of MsalUiRequiredException (in-repo copy of #3910) by @iarekk in AzureAD/microsoft-identity-web#3941 * Use MSAL's recent UserFIC API for agentic flows by @Avery-Dunn in AzureAD/microsoft-identity-web#3842 * Restore CustomizeHttpRequestMessage to run after the authorization header by @neha-bhargava in AzureAD/microsoft-identity-web#3943 * Bump Microsoft.IdentityModel.Tokens.Saml from 5.7.0 to 8.19.1 by @dependabot[bot] in AzureAD/microsoft-identity-web#3909 * Revert #3909: keep OWIN Saml/WsFederation on 5.7.0 by @iarekk in AzureAD/microsoft-identity-web#3944 * Bump Microsoft.Identity.Abstractions from 12.4.0 to 12.5.0 by @neha-bhargava in AzureAD/microsoft-identity-web#3947 * Add OnBeforeAuthHeaderCreation / OnAfterAuthHeaderCreation hooks to DownstreamApi by @neha-bhargava in AzureAD/microsoft-identity-web#3942 * Update IdentityModelV5Version and SamlPackageVersion to 5.7.1 in proj… by @trwalke in AzureAD/microsoft-identity-web#3950 * Rename retired MSALMSIV2 agent pool to MISEManagedIdentity by @gladjohn with @Copilot in AzureAD/microsoft-identity-web#3949 * Improve IDW10109 error handling for credential loading failures by @Avery-Dunn in AzureAD/microsoft-identity-web#3946 * Bump MSAL dependencies to 4.86.1 in central props by @gladjohn with @Copilot in AzureAD/microsoft-identity-web#3953 * Bump the notsecurity group with 3 updates by @dependabot[bot] in AzureAD/microsoft-identity-web#3954 **Full Changelog**: AzureAD/microsoft-identity-web@4.13.0...4.13.2 Commits viewable in [compare view](AzureAD/microsoft-identity-web@4.13.0...4.13.2). </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This was referenced Jul 21, 2026
Closed
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces the internal ROPC piggybacking mechanism for agentic User FIC token acquisition with MSAL .NET's native
AcquireTokenByUserFederatedIdentityCredentialAPI. This resolves a customer-reported caching bug (#3840), modernizes the agentic flow to use purpose-built MSAL APIs, and simplifies the implementation.Background
ID Web's agentic User FIC flow previously hijacked the ROPC (
AcquireTokenByUsernamePassword) path via an internal add-in (AgentUserIdentityMsalAddIn) that rewrote HTTP request bodies at the last moment. This had several drawbacks:ClaimsPrincipalwith oid/tid claims. In agentic scenarios,ClaimsPrincipalis typically null, so the cache was always bypassed — causing 2–4 unnecessary network calls per request (#3840).MSAL .NET's
AcquireTokenByUserFederatedIdentityCredentialis a first-class API for this scenario with built-in cache support. Version 4.84.2 added theGuid userObjectIdoverload for OID-based flows.Approach
Multi-CCA Pattern
AcquireTokenForClient+WithFmiPath(agentAppId).AcquireTokenForClient→ T2) and Leg 3 (AcquireTokenByUserFederatedIdentityCredential→ user token).Both use MSAL's shared static cache (
EnableSharedCacheOptions), providing natural cache key isolation via distinctClientIdvalues while ensuring tokens survive CCA re-creation.Three-Leg Flow
On subsequent calls for the same (agent, user, tenant) tuple, step 3 returns the cached token with zero network calls.
Account Identifier Storage
A
ConcurrentDictionary<string, string>maps"{agentAppId}:{USER_IDENTIFIER}:{TENANTID}"→ MSAL account identifier. This replaces the role thatClaimsPrincipaloid/tid claims serve in other ID Web flows. Entries are cleaned up when the CCA dictionary is cleared at the size threshold.Agent CCA Eviction
As DOS protection, the agent CCA dictionary is cleared entirely when it exceeds a configurable threshold (default 10,000). Since all agent CCAs use MSAL's shared static cache, clearing the dictionary only discards lightweight CCA objects — tokens remain accessible to newly-built CCAs via
AcquireTokenSilent.Tenant Propagation
The assertion callback extracts the tenant from
AssertionRequestOptions.TokenEndpoint(when the host matches the configured instance) and appliesWithTenantIdto Leg 1. This ensures multi-tenant scenarios work correctly, matching the pattern used byOidcIdpSignedAssertionProvider.Changes
Directory.Build.propsGuid userObjectIdoverload)TokenAcquisition.csTryGetAuthenticationResultForAgentUserFicAsync(new): Detects UPN/OID agentic flows, performs silent retrieval or the 3-leg flow via native MSAL APIsGetOrBuildAgentUserFicCcaAsync(new): Builds and caches agent CCAs with assertion callbacks that chain to the blueprint CCA; applies shared cache and size-threshold evictionExtractTenantFromTokenEndpointIfSameInstance(new): Extracts tenant from token endpoint URL when host matches configured instanceTryGetAuthenticationResultForConfidentialClientUsingRopcAsync: Intercepts agentic flows before the ROPC pathMsalExceptioninstead ofMsalUiRequiredExceptionTokenAcquisition.Logger.csLoggerMessage.Define):AgentUserFicFlowDetected,AgentUserFicSilentSuccess,AgentUserFicSilentFailureAgentUserFicAcquisitionComplete,AgentCcaCreated,AgentCcaEvictionLoggingEventId.csAgentIdentitiesExtension.csAddAgentIdentities()(AddOidcFic()preserved)AgentUserIdentityMsalAddIn.csTokenAcquisitionTests.csExtractTenantFromTokenEndpointIfSameInstancetests: Same/different instance, null inputs, invalid URINo Breaking Changes
All public APIs are unchanged:
WithAgentUserIdentity(options, agentAppId, username)— now uses native UPN path internallyWithAgentUserIdentity(options, agentAppId, userId)— now uses native OID path internallyAddAgentIdentities()— still registers OidcFic; no longer registers the (internal) add-in callbackThe deleted
AgentUserIdentityMsalAddInwasinternal staticwith no external consumers.Known Limitations
api://AzureADTokenExchange/.default(public cloud). National cloud support requires cloud-aware inference in MSAL itself — to be addressed in a follow-up.Resolves
ClaimsPrincipalis null