Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: AzureAD/microsoft-authentication-library-for-dotnet
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 4.86.1
Choose a base ref
...
head repository: AzureAD/microsoft-authentication-library-for-dotnet
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 4.87.0
Choose a head ref
  • 14 commits
  • 53 files changed
  • 6 contributors

Commits on Jul 16, 2026

  1. chore: add 4.86.1 changelog section and verify Public API state (#6129)

    * Initial plan
    
    * chore: add 4.86.1 changelog section
    
    ---------
    
    Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
    Copilot authored Jul 16, 2026
    Configuration menu
    Copy the full SHA
    ea50871 View commit details
    Browse the repository at this point in the history
  2. Add MSIv2 FIC two-leg E2E test (bearer token) (#5992)

    * Add MSIv2 FIC two-leg OBO e2e test (bearer token)
    
    New test: ManagedIdentityImdsV2FicTests
    - FIC two-leg flow: MSI Leg 1 (mTLS PoP for api://AzureADTokenExchange) → ConfApp Leg 2 (bearer token)
    - Covers SAMI and UAMI-ClientId variants via DataRow
    - Validates Leg 1 token type (mtls_pop), BindingCertificate, and token source
    - Validates Leg 2 bearer token type and cache hit on second call
    - Test category: MI_E2E_ImdsV2_Fic
    - TODO markers for FicConfAppClientId and TenantId (to be filled from CI environment
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Use LabResponseHelper/KeyVault pattern for ConfApp config in FIC test
    
    Replace hardcoded TODO constants with LabResponseHelper.GetAppConfigAsync(KeyVaultSecrets.AppS2S)
    so the test self-configures from Key Vault in CI, consistent with integration test patterns.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Use MI_E2E_ImdsV2 category so test runs in existing pipeline filter
    
    Pipeline filter is: TestCategory=MI_E2E_ImdsV2|TestCategory=MI_E2E_ImdsV2_Attested
    The custom MI_E2E_ImdsV2_Fic category was not in the filter so tests were skipped.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix FIC test: use MSI-based KV auth instead of LabResponseHelper
    
    The MSALMSIV2 pool VM does not have the lab certificate required by
    LabResponseHelper, causing TypeInitializationException on test startup.
    
    Replace LabResponseHelper.GetAppConfigAsync with GetConfAppConfigViaMsiAsync,
    which uses the VM's system-assigned managed identity to authenticate to
    id4skeyvault.vault.azure.net and read App-S2S-Config directly.
    
    Also add CryptographicException handling in Leg 1 consistent with the
    existing ManagedIdentityImdsV2Tests pattern.
    
    Prerequisite: the MSALMSIV2 pool SAMI must have read access to
    id4skeyvault.vault.azure.net (same vault the LabResponseHelper uses).
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Simplify FIC test: hardcode ConfApp ID per Gladwin's feedback
    
    Replace the MSI-based KeyVault lookup with hardcoded constants,
    consistent with the pattern used throughout ManagedIdentityImdsV2Tests
    and already established in ClientCredentialsMtlsPopTests for the same
    MSI-team ConfApp (163ffef9 / bea21ebe tenant).
    
    Also reverts the Azure.Security.KeyVault.Secrets project reference
    added in the previous commit — no longer needed.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Update ManagedIdentityImdsV2FicTests.cs
    
    * Update ManagedIdentityImdsV2FicTests.cs
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    Co-authored-by: Gladwin Johnson <90415114+gladjohn@users.noreply.github.com>
    3 people authored Jul 16, 2026
    Configuration menu
    Copy the full SHA
    f88e86b View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    0bf1621 View commit details
    Browse the repository at this point in the history
  4. Update Azure Arc managed identity API version from 2019-11-01 to 2020…

    …-06-01 (#6130)
    
    * Initial plan
    
    * Update Azure Arc managed identity api-version from 2019-11-01 to 2020-06-01
    
    ---------
    
    Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
    Copilot authored Jul 16, 2026
    Configuration menu
    Copy the full SHA
    ec3d646 View commit details
    Browse the repository at this point in the history

Commits on Jul 20, 2026

  1. Add MSIv2 FIC two-leg E2E test (mTLS PoP token in Leg 2) (#6132)

    * Add MSIv2 FIC two-leg E2E test (mTLS PoP token in Leg 2)
    
    Extends ManagedIdentityImdsV2FicTests with a Leg 2 mTLS PoP variant: Leg 2 calls .WithMtlsProofOfPossession() so the exchanged token is mtls_pop with a binding certificate, complementing the existing bearer test. Extracts the shared Leg 1 acquisition into AcquireLeg1MtlsPopTokenAsync, reused by both the bearer and PoP tests. Covers SAMI and UAMI-ClientId.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    Copilot-Session: 5ad57850-7d1f-4b9a-bf9f-723d69a9687c
    
    * Harden FIC Leg 2 cache assertions (address review)
    
    Assert the first Leg 2 call is TokenSource.IdentityProvider in both the bearer and mtls_pop tests, so
    the subsequent TokenSource.Cache check proves "fresh then cached" rather than passing when call 1 was
    already served from cache. Also assert the cached mtls_pop result retains its BindingCertificate, so a
    regression that drops the binding on cache retrieval is caught.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    Copilot-Session: b9c58d68-cc06-4afb-8c19-8e863d35f198
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    gladjohn and Copilot authored Jul 20, 2026
    Configuration menu
    Copy the full SHA
    a1db512 View commit details
    Browse the repository at this point in the history

Commits on Jul 21, 2026

  1. Add CI stage to deploy ManagedIdentityWebApi to Easy Auth-protected w…

    …eb app (#6135)
    
    * Add CI stage to deploy ManagedIdentityWebApi to Easy Auth-protected web app
    
    Adds an optional stage (gated by RunManagedIdentityWebAppDeploy) that builds and publishes the ManagedIdentityWebApi dev app, deploys it to the Easy Auth-protected App Service via the publish profile stored in the msidlabs Key Vault (Kudu zip deploy), then verifies the protected endpoint by acquiring an app-only token with the LabAuth certificate and calling it with a bearer token. The existing GitHub Action is left in place.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    Copilot-Session: 3d6c7cd0-e9c3-44bf-8d96-19c3175dcb9f
    
    * Build MI webapp with -p:NetCoreOnly=true to avoid mobile workloads on Windows agent
    
    The ManagedIdentityWebApi references the multi-targeted Microsoft.Identity.Client project, which includes net8.0-ios/net8.0-android on Windows and requires MAUI workloads not present on the hosted agent. NetCoreOnly restricts it to netstandard2.0 + net8.0.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    Copilot-Session: 3d6c7cd0-e9c3-44bf-8d96-19c3175dcb9f
    
    * Use RSACertificateExtensions.GetRSAPrivateKey for Windows PowerShell 5.1 compatibility
    
    The ADO powershell task runs Windows PowerShell 5.1 (.NET Framework), where GetRSAPrivateKey is an extension method, not an instance method. Call it statically so the client-assertion signing works on the hosted agent.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    Copilot-Session: 3d6c7cd0-e9c3-44bf-8d96-19c3175dcb9f
    
    * Address PR review: pin --framework on build/publish and document v1 token alignment
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    Copilot-Session: 3d6c7cd0-e9c3-44bf-8d96-19c3175dcb9f
    
    * Add UAMI coverage to MI webapp deploy/test stage
    
    Adds a UserAssignedClientId parameter and a second endpoint check (userAssignedId) so the stage verifies both system-assigned and user-assigned managed identity token acquisition through Easy Auth. Validated live: anonymous=401, SAMI and UAMI both return Access token received.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    Copilot-Session: 3d6c7cd0-e9c3-44bf-8d96-19c3175dcb9f
    
    * Address review: write LabAuth PFX to agent temp and preserve last error on retry exhaustion
    
    Write the LabAuth client PFX to $(Agent.TempDirectory) instead of the source workspace so the private key is not picked up by artifact publishing/diagnostics. Track the last HTTP error in the endpoint retry loop and throw it when all attempts fail, so CI failures show the real cause instead of a null response.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    Copilot-Session: 3d6c7cd0-e9c3-44bf-8d96-19c3175dcb9f
    
    * Delete LabAuth PFX from agent after use (always-run cleanup step)
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    Copilot-Session: 3d6c7cd0-e9c3-44bf-8d96-19c3175dcb9f
    
    * Extract deploy/test PowerShell into build/scripts and reuse shared KeyVault template
    
    Reuses template-install-keyvault-secrets.yaml for the LabAuth fetch + certificate install (instead of duplicating it), fetches only the publish-profile secret separately, and moves the deploy and endpoint-test logic into build/scripts/*.ps1. Removes the self-managed PFX handling and cleanup step since the shared template now owns the certificate.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    Copilot-Session: 3d6c7cd0-e9c3-44bf-8d96-19c3175dcb9f
    
    * Harden MI webapp test script: EphemeralKeySet cert load and RSA null check
    
    Load the LabAuth certificate with EphemeralKeySet (sign-only, no on-disk key persistence) and fail fast with a clear message if the RSA private key cannot be loaded, instead of a generic null-reference in SignData.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    Copilot-Session: 3d6c7cd0-e9c3-44bf-8d96-19c3175dcb9f
    gladjohn authored Jul 21, 2026
    Configuration menu
    Copy the full SHA
    4cb172d View commit details
    Browse the repository at this point in the history
  2. Delete old web app e2e test (#6136)

    Delete .github/workflows/deploy-managed-identity-webapi.yml
    gladjohn authored Jul 21, 2026
    Configuration menu
    Copy the full SHA
    e0a7b08 View commit details
    Browse the repository at this point in the history

Commits on Jul 22, 2026

  1. Use PSS padding in KeyGuard liveness probe (CodeQL SM03799) (#6141)

    The CanSign liveness probe signed a throwaway 1-byte payload with
    RSASignaturePadding.Pkcs1, which CodeQL flags via
    cs/cryptography/rsa-unapproved-signing-padding-scheme (SM03799).
    Switch the probe to the approved PSS padding, consistent with the
    rest of the MI/PoP signing code (Csr, InMemoryCryptoProvider, etc.).
    The probe only verifies key material liveness; the signature is
    discarded, so the padding change has no functional impact.
    gladjohn authored Jul 22, 2026
    Configuration menu
    Copy the full SHA
    224a50a View commit details
    Browse the repository at this point in the history
  2. Expose MsalServiceException.ErrorCodesForLogging for diagnostics (#6138)

    * Expose MsalServiceException.ErrorCodes for diagnostics
    
    Promote ErrorCodes from internal string[] to a public
    IReadOnlyList<string> (getter only; setter stays internal) so
    downstream callers can surface the raw STS error codes (numeric
    AADSTS codes) for diagnostics and logging.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    Copilot-Session: d296b5aa-33db-4934-a697-cdf1c1999e09
    
    * Address review: rename to ErrorCodesForLogging, return read-only copy (Bug 3696281)
    
    - Rename the new public MsalServiceException.ErrorCodes to ErrorCodesForLogging
      per PR feedback, matching the sibling SubErrorForLogging and signalling it is
      a diagnostics-only surface (property is still unshipped, so no break).
    - Wrap the backing string[] in Array.AsReadOnly so callers cannot downcast the
      IReadOnlyList and mutate the exception's error codes.
    - Fix the CHANGELOG placeholder link (#TBD -> #6138) and property name.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    Copilot-Session: d296b5aa-33db-4934-a697-cdf1c1999e09
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    neha-bhargava and Copilot authored Jul 22, 2026
    Configuration menu
    Copy the full SHA
    5078abc View commit details
    Browse the repository at this point in the history
  3. Populate ExecutionResult.Exception for non-MSAL failures (Bug 3696306) (

    #6139)
    
    * Populate ExecutionResult.Exception for non-MSAL failures (Bug 3696306)
    
    The OTel tags enricher received ExecutionResult.Exception = null when a
    token acquisition failed with a non-MsalException, because RequestBase's
    generic catch passed no exception to LogFailureTelemetryToOtel. It now
    hands the enricher a telemetry-only MsalException wrapper (originating
    type as ErrorCode, original message, original exception as InnerException,
    plus failure metadata), mirroring the MsalException path. The original
    exception is still re-thrown unchanged, so caller-observable behavior is
    unaffected.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    Copilot-Session: d296b5aa-33db-4934-a697-cdf1c1999e09
    
    * Guard telemetry-only wrapper against empty message/null type name (Bug 3696306)
    
    Address PR review: the non-MSAL enricher wrapper used ex.GetType().FullName
    and ex.Message directly, but the MsalException ctor rejects a null/whitespace
    errorCode or errorMessage. An original exception with an empty message (or a
    null Type.FullName for some generic/array types) would therefore raise an
    ArgumentNullException that replaced the original exception, breaking the
    rethrow-unchanged guarantee. Fall back to the type name in both cases and add
    a regression test for the empty-message path.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    Copilot-Session: d296b5aa-33db-4934-a697-cdf1c1999e09
    
    * Surface AuthenticationResultMetadata on non-MSAL failures via Exception.Data (3696194) (#6140)
    
    Expose AuthenticationResultMetadata on non-MSAL failures via Exception.Data (Bug 3696194)
    
    When a token acquisition fails with a non-MsalException, MSAL now stashes the
    failure AuthenticationResultMetadata (durations, cache-refresh reason, token
    endpoint, region) on the original exception's Data bag under the new public
    MsalException.AuthenticationResultMetadataKey. Downstream header-creation
    providers that catch the raw exception can surface token-acquisition
    diagnostics without MSAL converting or wrapping the thrown exception. The
    original exception is re-thrown unchanged; the write is guarded so it never
    masks the caller's exception.
    
    
    Copilot-Session: d296b5aa-33db-4934-a697-cdf1c1999e09
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Mark AuthenticationResultMetadata [Serializable] on .NET Framework/netstandard (3696194)
    
    The Exception.Data write added for 3696194 throws ArgumentException 'not serializable' on .NET Framework, whose ListDictionaryInternal rejects non-serializable values, replacing the caller's original exception (17 net48 test failures). .NET Core removed that check. Mark AuthenticationResultMetadata and its RegionDetails member [Serializable] only under NETFRAMEWORK || NETSTANDARD; the whole graph is serializable so the write succeeds on every target and metadata is delivered uniformly. No public-API or test changes needed.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    Copilot-Session: d296b5aa-33db-4934-a697-cdf1c1999e09
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    Copilot-Session: d296b5aa-33db-4934-a697-cdf1c1999e09
    neha-bhargava and Copilot authored Jul 22, 2026
    Configuration menu
    Copy the full SHA
    1159aa4 View commit details
    Browse the repository at this point in the history

Commits on Jul 23, 2026

  1. Remove experimental features from client setup (#6143)

    Removed experimental features option from client application setup.
    gladjohn authored Jul 23, 2026
    Configuration menu
    Copy the full SHA
    4680156 View commit details
    Browse the repository at this point in the history
  2. Add client-side opaque-token log scrubber (#6119)

    * Add client-side opaque-token log scrubber
    
    Redact HIT-tagged opaque tokens from MSAL log output at the FormatLogMessage choke point. Adds TokenScrubber with an AppContext kill switch and unit tests.
    
    * Add more token-scrubbing test examples
    
    Covers token at start/end, whole-string token, base64url expansion across '=', Bearer header, multiple Set-Cookie tokens on one line, adjacent tokens, mixed eSTS+MSA, HTTP response error blob, null/empty inputs.
    
    * Fold fast-path and first-match into a single scan in TokenScrubber
    
    Addresses PR review: Scrub() previously scanned for patterns twice on the redaction path (ContainsAnyPattern then FindEarliestMatch from index 0). Now performs a single FindEarliestMatch; the no-match fast path still returns the same reference with no allocation.
    
    * Scope token scrubbing to exception and ESTS messages
    
    Per review feedback, replace the global FormatLogMessage scrub with a tactical fix: scrub only exception log messages (which carry ESTS request/response/error bodies via MsalServiceException) in the MsalLoggerExtensions exception overloads. Ordinary log lines are no longer scrubbed. TokenScrubber internals are unchanged. Adds LoggerTests integration tests proving exception messages are scrubbed and plain messages are not.
    
    * Scrub only the exception message in *WithPrefix log overloads
    
    Address review feedback to run the scrubber on just the message content rather than the whole formatted line. ErrorPiiWithPrefix/WarningPiiWithPrefix now scrub exWithPii.ToString() and append the prefix afterward, matching the other exception overloads.
    
    * Restore null-exception tolerance in *WithPrefix log overloads
    
    Use exWithPii?.ToString() so ErrorPiiWithPrefix/WarningPiiWithPrefix do not
    throw when the exception is null, matching the pre-scrubber behavior.
    
    * Guard exception log scrubbing behind IsLoggingEnabled
    
    Add an early IsLoggingEnabled check to the exception-logging overloads so
    exWithPii?.ToString() and TokenScrubber.Scrub(...) only run when the target
    log level is enabled, avoiding O(n) scans of large exception text on disabled
    paths. Also normalize the remaining .ToString() calls to ?.ToString() for
    uniform null tolerance. Behavior-preserving: both logger adapters already gate
    their Log body on IsLoggingEnabled.
    4gust authored Jul 23, 2026
    Configuration menu
    Copy the full SHA
    06ae3da View commit details
    Browse the repository at this point in the history
  3. Forward OpenTelemetry tags enricher to the client-assertion callback …

    …(AB#3696484) (#6142)
    
    Forward OtelTagsEnricher to the client-assertion callback via AssertionRequestOptions
    
    Surfaces the outer request's WithOtelTagsEnricher delegate on AssertionRequestOptions
    so a client-assertion callback that acquires the assertion via an inner token request
    (e.g. a Federated Identity Credential) can enrich the inner acquisition's OTel metrics
    identically to the outer request. Additive/optional; null when no enricher configured.
    
    Work item: 3696484
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
    Copilot-Session: d296b5aa-33db-4934-a697-cdf1c1999e09
    3 people authored Jul 23, 2026
    Configuration menu
    Copy the full SHA
    bef268f View commit details
    Browse the repository at this point in the history

Commits on Jul 24, 2026

  1. Expose WithOtelTagsEnricher for managed identity requests (AB#3696484) (

    #6144)
    
    Expose WithOtelTagsEnricher for managed identity requests
    
    The existing WithOtelTagsEnricher extension targets AbstractAcquireTokenParameterBuilder<T>,
    which managed identity builders do not inherit (they derive from
    AbstractManagedIdentityAcquireTokenParameterBuilder<T> : BaseAbstractAcquireTokenParameterBuilder<T>),
    so the OpenTelemetry tags enricher could not be set on an MI request even though the MI
    background-refresh path (ManagedIdentityAuthRequest -> ProcessFetchInBackground) already reads it.
    
    Add an additive MI-targeted WithOtelTagsEnricher overload (new extension type, existing method
    untouched) plus a unit test asserting the enricher fires on the MI proactive background refresh.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    Copilot-Session: d296b5aa-33db-4934-a697-cdf1c1999e09
    neha-bhargava and Copilot authored Jul 24, 2026
    Configuration menu
    Copy the full SHA
    39d2001 View commit details
    Browse the repository at this point in the history
Loading