Skip to content

Mark projects as AOT compatible - #3998

Open
Avery-Dunn wants to merge 1 commit into
masterfrom
avdunn/aot-compatibility
Open

Mark projects as AOT compatible#3998
Avery-Dunn wants to merge 1 commit into
masterfrom
avdunn/aot-compatibility

Conversation

@Avery-Dunn

Copy link
Copy Markdown
Contributor

Referencing the Microsoft.Identity.Web.OidcFIC package (the FIC signed-assertion loader used for agentic / cross-cloud Federated Identity Credential scenarios) breaks a trimmed or Native AOT publish of the consuming application. The failure surfaces as an IL2026 trim warning that is promoted to a build error, e.g.:

ILLink : IL2026: Microsoft.Identity.Web.OidcFic.OidcIdpSignedAssertionLoader...
  Using 'ConfigurationBinder.Bind(IConfiguration, Object)' which has
  'RequiresUnreferencedCodeAttribute' can break functionality when trimming...
error NETSDK1144: Optimizing assemblies for size failed.

Root cause

OidcIdpSignedAssertionLoader.LoadIfNeededAsync binds a configuration section to
MicrosoftIdentityApplicationOptions using the reflection-based configuration binder:

configuration.GetSection(sectionName).Bind(microsoftIdentityApplicationOptions);

ConfigurationBinder.Bind(IConfiguration, object) is annotated [RequiresUnreferencedCode] / [RequiresDynamicCode]. When an application is published with trimming (PublishTrimmed) or Native AOT (PublishAot), ILLink/ILC analyze the
whole call graph, walk into OidcFIC, and report IL2026 (and IL3050 under AOT) for this unguarded reflection call.

Unlike the rest of Microsoft Identity Web, the OidcFIC project set no trim/AOT properties:

  • It did not enable the compile-time trim/AOT analyzers (IsAotCompatible), so the issue was never caught in this repo's own build.
  • It did not enable the configuration-binding source generator (EnableConfigurationBindingGenerator), so the reflection-based binder remained in the shipped IL.
  • The AOT compatibility test app did not root the OidcFIC assembly, so the gap was not covered by AOT validation.

Changes

All changes are build/packaging configuration and follow the exact pattern already used by Microsoft.Identity.Web.DownstreamApi, Microsoft.Identity.Web.MicrosoftGraph, and the AOT compatibility test app.

1. src/Microsoft.Identity.Web.OidcFIC/Microsoft.Identity.Web.OidcFIC.csproj

<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0'))">
  <EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
  <IsAotCompatible>true</IsAotCompatible>
  <!-- The configuration binding source generator emits these diagnostics for the certificate
       object graph on MicrosoftIdentityApplicationOptions (X509Certificate2, PublicKey, PrivateKey,
       etc.), which is never populated from configuration. Suppressed to match the AOT test app. -->
  <NoWarn>$(NoWarn);SYSLIB1100;SYSLIB1101;SYSLIB0026;SYSLIB0027;SYSLIB0028</NoWarn>
</PropertyGroup>

2. Regression hardening for sibling packages

In addition to OidcFIC assembly which threw the original issue, two leaf libraries were verified to be trim/AOT-clean but were not yet marked as being compatible. They are now marked IsAotCompatible (net8.0+) to avoid them causing the same errors:

  • src/Microsoft.Identity.Web.AgentIdentities/Microsoft.Identity.Web.AgentIdentities.csproj (the agentic-identity package, which references OidcFIC).
  • src/Microsoft.Identity.Web.Certificateless/Microsoft.Identity.Web.Certificateless.csproj.

3. tests/Microsoft.Identity.Web.AotCompatibility.TestApp

An existing test app intended to cover AOT compatibility, but did not reference either OidcFIC or AgentIdentities. This PR adds them to the TrimmerRootAssembly list so the FIC / agentic path is actually exercised by an AOT publish and this class of regression is caught going forward:

<TrimmerRootAssembly Include="Microsoft.Identity.Web.OidcFIC"/>
<TrimmerRootAssembly Include="Microsoft.Identity.Web.AgentIdentities"/>

Verification

  • Reproduced the original IL2026/IL3050 at OidcIdpSignedAssertionLoader.cs by building OidcFIC with the AOT analyzers enabled.
  • Multi-TFM build of OidcFIC (net8.0/net9.0/net10.0 + net462/net472/netstandard2.0) with the repo default TreatWarningsAsErrors=true: 0 warnings, 0 errors.
  • Trimmed publish of a consumer app that roots the OidcFIC assembly (net8.0): 0 IL2026/IL3050/NETSDK1144.
  • Native AOT publish of the AOT test app (net10.0) with OidcFIC rooted: the entire managed IL scan / trim-and-AOT analysis phase completed with 0 warnings (only the final native link step fails in the local environment because the C++ linker is not on PATH — an environment limitation, not a code issue).
  • Existing unit tests: all 9 OidcIdpSignedAssertionLoader tests pass — binding behavior is preserved.

net8/9 gap follow-up

This PR is the limited fix for a customer-reported issue: it makes the OidcFIC package (and the verified sibling leaf libraries) trim-/AOT-clean on net8.0, net9.0, and net10.0.

It does not attempt to deliver end-to-end trim/AOT support for a full Microsoft Identity Web web app / web API on net8/9. Investigation showed that the AOT-safe web-API entry point — AddMicrosoftIdentityWebApiAot and its supporting
MicrosoftIdentityJwtBearerOptionsPostConfigurator — is gated behind #if NET10_0_OR_GREATER. On net8/9 the only configuration path is the reflection-based AddMicrosoftIdentityWebApi(IConfiguration, ...), which is inherently not AOT-safe. This is the deliberate reason the AOT compatibility test app and TokenAcquisition's IsAotCompatible marker are net10-focused.

The individual leaf libraries (TokenAcquisition, OidcFIC, AgentIdentities, Certificateless) were confirmed to be trim/AOT-clean on net8/9 in isolation. Closing the full net8/9 gap would require back-porting the reflection-free web-API configuration surface (AddMicrosoftIdentityWebApiAot et al.) to net8/9 — a separate, larger effort tracked independently.

@Avery-Dunn
Avery-Dunn requested a review from a team as a code owner August 6, 2026 21:07
<!-- The configuration binding source generator emits these diagnostics for the certificate
object graph on MicrosoftIdentityApplicationOptions (X509Certificate2, PublicKey, PrivateKey,
etc.), which is never populated from configuration. Suppressed to match the AOT test app. -->
<NoWarn>$(NoWarn);SYSLIB1100;SYSLIB1101;SYSLIB0026;SYSLIB0027;SYSLIB0028</NoWarn>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think this will solve the customer's issue. Ultimtately those properties are not AOT compatible and removing them from config is a breaking change.

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.

Agreed this moves the compile time issue into a runtime issue

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Bogdan Gavril (@bgavrilMS) You say removing them from the config is a breaking change, but you also approved the PR.

So, does that mean it's worth making it runtime issue instead of a compile time issue (as MARCIN Z (@MZOLN) described it)? Or would it be better to solve the runtime issues as well before merging?

Shifting it to a runtime issue might help the specific customer who asked about it (since it was just being pulled in transitively for them), but could cause more confusing problems if the incompatible stuff ends up getting referenced at runtime.

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.

How would shifting this to runtime issue help?

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.

Pull request overview

This PR addresses trimming/Native AOT publish failures caused by reflection-based configuration binding in Microsoft.Identity.Web.OidcFIC by enabling the configuration-binding source generator and marking relevant libraries as AOT compatible, aligning OidcFIC (and related leaf packages) with established patterns already used in other Microsoft Identity Web packages.

Changes:

  • Enable EnableConfigurationBindingGenerator and set IsAotCompatible (net8.0+) for Microsoft.Identity.Web.OidcFIC, with targeted SYSLIB* suppressions matching the existing AOT test app pattern.
  • Mark Microsoft.Identity.Web.AgentIdentities and Microsoft.Identity.Web.Certificateless as IsAotCompatible (net8.0+).
  • Extend the AOT compatibility test app to root Microsoft.Identity.Web.OidcFIC and Microsoft.Identity.Web.AgentIdentities assemblies so the trim/AOT analysis includes these paths.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
tests/Microsoft.Identity.Web.AotCompatibility.TestApp/Microsoft.Identity.Web.AotCompatibility.TestApp.csproj Roots OidcFIC and AgentIdentities so AOT publish/trim analysis exercises the FIC/agentic path.
src/Microsoft.Identity.Web.OidcFIC/Microsoft.Identity.Web.OidcFIC.csproj Enables config-binding source generator + marks AOT compatibility (net8+), and suppresses known SYSLIB generator diagnostics consistent with the test app.
src/Microsoft.Identity.Web.Certificateless/Microsoft.Identity.Web.Certificateless.csproj Marks the package as AOT compatible for net8.0+ TFMs.
src/Microsoft.Identity.Web.AgentIdentities/Microsoft.Identity.Web.AgentIdentities.csproj Marks the package as AOT compatible for net8.0+ TFMs.

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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants