Skip to content

AoT - Part 5: Extract shared IdentityOptionsHelpers for AOT and non-AOT paths #3706

@jmprieur

Description

@jmprieur

Problem Statement

Both the existing (MergedOptions-based) and AOT-style configuration paths in Microsoft.Identity.Web duplicate core logic for authority construction, event chaining, and validation. Sharing helper logic ensures correctness, reduces maintenance burden, and simplifies review/testing.

Design Reference (POC)

Implementation is already validated in Draft PR #3705 (copilot/aot-compatibility-updates branch).

Do NOT regenerate — extract the relevant files from that branch.

Key Files to Extract

File Link
Internal/IdentityOptionsHelpers.cs View
WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs View
PublicAPI/net10.0/InternalAPI.Unshipped.txt View
PublicAPI/net9.0/InternalAPI.Unshipped.txt View
PublicAPI/net8.0/InternalAPI.Unshipped.txt View
PublicAPI/net472/InternalAPI.Unshipped.txt View
PublicAPI/net462/InternalAPI.Unshipped.txt View
PublicAPI/netstandard2.0/InternalAPI.Unshipped.txt View

Extraction Guide

# 1. Create branch from jmprieur/aoT
git checkout -b jmprieur/shared-helpers jmprieur/aoT
git fetch origin copilot/aot-compatibility-updates

# 2. Extract shared helpers files
git checkout origin/copilot/aot-compatibility-updates -- \
  src/Microsoft.Identity.Web/Internal/IdentityOptionsHelpers.cs \
  src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs \
  src/Microsoft.Identity.Web/PublicAPI/net10.0/InternalAPI.Unshipped.txt \
  src/Microsoft.Identity.Web/PublicAPI/net9.0/InternalAPI.Unshipped.txt \
  src/Microsoft.Identity.Web/PublicAPI/net8.0/InternalAPI.Unshipped.txt \
  src/Microsoft.Identity.Web/PublicAPI/net472/InternalAPI.Unshipped.txt \
  src/Microsoft.Identity.Web/PublicAPI/net462/InternalAPI.Unshipped.txt \
  src/Microsoft.Identity.Web/PublicAPI/netstandard2.0/InternalAPI.Unshipped.txt

# 3. IMPORTANT: Clean up InternalAPI.Unshipped.txt files
#    Remove entries for MicrosoftIdentityJwtBearerOptionsPostConfigurator (belongs in Part 3)
#    Keep only IdentityOptionsHelpers entries

# 4. Commit
git add -A
git commit -m "Extract shared IdentityOptionsHelpers for AOT and non-AOT paths"
git push -u origin jmprieur/shared-helpers

⚠️ Manual Cleanup Required

The InternalAPI.Unshipped.txt files from the POC branch include entries for MicrosoftIdentityJwtBearerOptionsPostConfigurator which belongs in Part 3.

Edit each InternalAPI.Unshipped.txt to keep only:

#nullable enable
Microsoft.Identity.Web.Internal.IdentityOptionsHelpers
static Microsoft.Identity.Web.Internal.IdentityOptionsHelpers.BuildAuthority(...) -> string!
static Microsoft.Identity.Web.Internal.IdentityOptionsHelpers.ChainTokenStorageHandler(...) -> System.Func<...>!
static Microsoft.Identity.Web.Internal.IdentityOptionsHelpers.ConfigureAudienceValidation(...) -> void
static Microsoft.Identity.Web.Internal.IdentityOptionsHelpers.ValidateRequiredOptions(...) -> void

Shared Helpers (what's included)

Helper Purpose
BuildAuthority() Authority URL construction for AAD/B2C/CIAM
ChainTokenStorageHandler() OnTokenValidated event handler for OBO
ConfigureAudienceValidation() AOT-safe audience validation setup
ValidateRequiredOptions() Validation (AOT path only, not wired to MergedOptions)

Design Decision

Do NOT refactor MergedOptionsValidation to use shared helpers because:

  • Different type hierarchies (MicrosoftIdentityApplicationOptions vs MergedOptions)
  • Empty string handling differences in merge logic
  • Minimal duplication (~30 lines)
  • Not worth the cross-assembly complexity

Work Checklist

  • Extract files from copilot/aot-compatibility-updates (do not regenerate)
  • Clean up InternalAPI.Unshipped.txt files (remove PostConfigurator entries)
  • Add IdentityOptionsHelpersTests.cs unit tests
  • Verify existing non-AOT path tests still pass
  • All TFMs build successfully

Related:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions