Skip to content

Move the authentication provider registry into Abstractions - #4670

Draft
paulmedynski wants to merge 12 commits into
dev/paul/assembly-signing-azurefrom
dev/paul/auth-registry-abstractions
Draft

paulmedynski wants to merge 12 commits into
dev/paul/assembly-signing-azurefrom
dev/paul/auth-registry-abstractions

Conversation

@paulmedynski

@paulmedynski paulmedynski commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Description

Removes the reflection bridge from Microsoft.Data.SqlClient.Extensions.Abstractions into Microsoft.Data.SqlClient by moving the authentication provider registry down into the layer both assemblies already share.

The problem

The public SqlAuthenticationProvider.GetProvider/SetProvider methods live in the Abstractions package, but the registry state they mutate lived in the core driver. Because the dependency arrow points SqlClient → Abstractions, Abstractions could not call the internal SqlAuthenticationProviderManager directly without a cycle — so it reflected. SqlAuthenticationProvider.Internal used Assembly.Load + MethodInfo.Invoke on every get/set.

The change

The manager's surface is typed on SqlAuthenticationProvider and SqlAuthenticationMethod, which already live in Abstractions. So the registry can sit there, and both sides call it with concrete, strongly-typed APIs against the same static state.

  • New AuthenticationProviderRegistry (internal) in Abstractions. Owns the ConcurrentDictionary<SqlAuthenticationMethod, ProviderEntry>, the IsSupported enforcement, the BeforeLoad/BeforeUnload lifecycle callbacks, and the permanent (application-specified) provider precedence rule.
  • SqlAuthenticationProvider.Internal.cs deleted (−198 lines). GetProvider/SetProvider now call the registry directly. Their signatures are unchanged.
  • SqlAuthenticationProviderManagerAuthenticationBootstrapper. The bootstrap half stays in the driver, where it belongs: app.config section parsing, SqlAuthenticationInitializer creation, and strong-name-verified Azure extension loading. It seeds the shared registry through SetPermanentProvider.
  • Lazy bootstrap. SqlConnectionInternal triggers the one-time initialization on the federated/Active Directory auth path rather than from a static constructor, so the Azure extension is loaded only when a connection actually authenticates.
  • Localized Strings resources added to Abstractions for the unsupported-method error that previously came from SQL.UnsupportedAuthenticationByProvider.

API changes / compatibility

No public API change. SqlAuthenticationProvider.GetProvider/SetProvider keep their signatures and semantics; the registry stays internal.

One accepted behavior difference: the default Azure provider now appears once the driver's bootstrap runs — i.e. when a connection authenticates — rather than being eagerly force-loaded from a static constructor. Conversely, a user's SetProvider call now works even if the core assembly has not been loaded yet, since the provider sits in the shared singleton until the driver reads it.

InternalsVisibleTo

Abstractions grants InternalsVisibleTo to Microsoft.Data.SqlClient (both the unsigned and product-key-signed forms) for one reason: config-specified provider precedence. A provider declared in app.config must be registered as non-overridable, so a later user SetProvider returns false instead of replacing it. That marking — SetPermanentProvider — is intentionally not public. The general get/set path does not need it.

Assembly size and performance

Code shifts from the driver into Abstractions; the former shrinks by roughly what the latter grows. Abstractions is a hard dependency of the driver and never ships without it, so total footprint is unchanged (net negative, after deleting the bridge). Get/set become direct calls instead of MethodInfo.Invoke, and the one-time Assembly.Load + reflection lookup in the static constructor is gone.

Issues

Prerequisite for the NativeAOT fix for #4193. This PR removes the Abstractions→SqlClient reflection edge structurally; the SqlClient→Azure discovery reflection is handled separately in the follow-up PR stacked on this one.

Testing

  • New AuthenticationProviderRegistryTest.cs (Abstractions) — get/set, IsSupported rejection, permanent-provider precedence, override semantics, BeforeLoad/BeforeUnload invocation and exception isolation.
  • New AuthenticationBootstrapperTests.cs (UnitTests) — config-driven discovery, application client ID, UseWamBroker parsing, initializer creation, registry seeding.
  • New AuthenticationBootstrapperTests.cs / AuthenticationBootstrapperGlobalTests.cs (Azure extension tests) — default provider installation via the bootstrapper.
  • Relocated the bootstrapper tests from FunctionalTests to UnitTests, which can see driver internals. SqlAuthenticationProviderManagerTests.cs and its app.config move with them.
  • Updated SqlAuthenticationProviderTest.cs to exercise the registry instead of the reflection bridge.

Validation on this branch:

  • Microsoft.Data.SqlClient + Abstractions + UnitTests build clean for net9.0, 0 warnings.
  • Unit tests: 1186 passed, 14 skipped. The single failure (SimulatedServerTests.ConnectionTests.IntegratedAuthConnectionTest, "Cannot generate SSPI context") is pre-existing and environmental — no Kerberos on the Linux test host.

Known follow-up

The Azure-extension loading trace calls relocated into AuthenticationBootstrapper.LoadAzureExtensionProvider use interpolated strings, so this branch does not carry #4528's parameterized trace-call conversion for that block. That conversion applied only to the code this PR rewrites. Worth re-applying before this leaves draft.

Stack

#4566 assembly-signing-sqlserver
  #4567 assembly-signing-logging
    #4568 assembly-signing-abstractions
      #4569 assembly-signing-sqlclient
        #4570 assembly-signing-azure
          THIS PR  auth-registry-abstractions
            #4573  aot-azure-fix

Split out of #4573, which previously combined this structural refactor with the AOT feature-switch work. #4573 is rebased onto this branch and now contains only the AOT changes.

Introduce the shared signing-key download step and thread isInternalBuild
through the CI core so the SqlServer package is strong-name signed on internal
Package-mode builds.

- Add eng/pipelines/common/steps/download-assembly-signing-key.yml, which
  exports driverKeyFile or testKeyFile from ADO secure files.
- Adopt that step in the OneBranch build and nightly CI package pipelines,
  renaming keyFile to driverKeyFile.
- Declare isInternalBuild in dotnet-sqlclient-ci-core.yml and set it from the
  CI package- and project-reference pipelines.
- Sign the SqlServer package when isInternalBuild is true and referenceType is
  not Project.
- Quote SigningKeyPath in buildProperties so the secure-file path is
  robust to spaces, matching build-buildproj-step.yml and
  sqlclient-ci-package-pipeline.yml.
- Move the BuildNumber/FileVersion note directly above buildProperties
  in both the signed and unsigned pack branches.

No change to signing behaviour: signing stays gated on internal
Package-reference builds.
- Split download-assembly-signing-key.yml into download-driver-signing-key-step.yml
  and download-test-signing-key-step.yml, each parameterless with its own output.
- Restore "strong-name signing" terminology; always name the driver or test key.
- Remove parameter defaults added in this branch; pass values explicitly, including
  isInternalBuild: false in both PR pipelines.
- Fold the driver key download into the existing signing conditional in the pack job.
Thread referenceType and isInternalBuild into the Logging stage and pack job so
the Logging package is strong-name signed on internal Package-mode builds.

Abstractions references Logging, so Logging must be signed before Abstractions
can be; a strong-named assembly referencing a weak-named one fails with CS8002,
which is an error here because TreatWarningsAsErrors is enabled.

Logging has no test project yet, so no test-assembly signing or signed
InternalsVisibleTo grant is added.
- Fix the signing key template reference to download-driver-signing-key-step.yml
- Quote SigningKeyPath to tolerate whitespace in the secure file path
- Collapse the duplicated isInternalBuild/referenceType conditional
- Drop parameter defaults for referenceType and isInternalBuild
- Use positive referenceType comparisons (eq 'Package')
…ions

Sign the Abstractions package and its test assembly on internal Package-mode
builds, and make the Abstractions CI jobs actually honour Package mode.

- Thread isInternalBuild through the Abstractions stage into the pack and test
  jobs, downloading the driver and test signing keys as needed.
- Add a signed InternalsVisibleTo grant for the test assembly, and sign the test
  assembly when a test key is supplied.
- Pass packageVersion, loggingArtifactsName and referenceType into the test
  jobs, and download the Logging artifacts, so Package mode is exercised.
- Correct the pack job to use the canonical SqlClientPackageVersion and
  BuildNumber properties instead of undeclared per-package parameters.
- Thread signing and reference-type arguments into the build.proj
  TestAbstractions target.
- Build the Abstractions test project for net462 only on Windows hosts.
Pre-emptively align this PR with the review feedback already addressed
lower in the stack, so the same comments aren't raised again.

- Reference the split download-driver-signing-key-step.yml and
  download-test-signing-key-step.yml templates instead of the removed
  download-assembly-signing-key.yml.
- Quote SigningKeyPath and TestSigningKeyPath to tolerate whitespace in
  the secure file paths.
- Fold the driver key download into the existing signing conditional in
  the pack job, removing the duplicated conditional.
- Use positive referenceType comparisons (eq 'Package').
- Drop the referenceType and isInternalBuild parameter defaults; both
  are already passed explicitly by every caller.
- Move the BuildNumber/FileVersion note directly above buildProperties
  in every pack branch.
- Restore "strong-name signing" terminology and name the driver or test
  key explicitly.
Sign the SqlClient and AKV Provider assemblies, and the SqlClient test
assemblies, on internal Package-mode CI builds.

SqlClient references Abstractions, Logging and SqlServer.Server, so those
packages must already be signed for this to build; a strong-named assembly
referencing a weak-named one fails with CS8002.

- Thread isInternalBuild from the CI core into the SqlClient package stage and
  the test stage, and download the driver and test signing keys in the build
  and test jobs.
- Pass signingKeyPath to the project build step and both signing key paths to
  the test steps.
- Thread SigningKeyPath into the build.proj TestSqlClientFunctional and
  TestSqlClientManual targets, and both key arguments into TestSqlClientUnit.
Pre-emptively align this PR with the review feedback already addressed
lower in the stack, so the same comments aren't raised again.

- Reference the split download-driver-signing-key-step.yml and
  download-test-signing-key-step.yml templates instead of the removed
  download-assembly-signing-key.yml.
- Use positive referenceType comparisons (eq 'Package').
- Drop the isInternalBuild parameter defaults; every caller already
  passes it explicitly.
- Use "strong-name signing" terminology and name the driver or test key
  in the signingKeyPath/testSigningKeyPath parameter docs, correcting
  the stale note about test-filter categories.
Sign the Azure package and its test assembly on internal Package-mode builds.

Azure references Abstractions and Logging, both of which are signed earlier in
this stack, so the reference closure is complete.

- Thread isInternalBuild from the CI core into the Azure stage, pack job and
  test jobs, downloading the driver and test signing keys as needed.
- Add a signed InternalsVisibleTo grant for the Azure test assembly, which
  needs internal access for the WAM broker tests, and sign that assembly when a
  test key is supplied.
- Thread signing arguments into the build.proj TestAzure target.
- Rename the test job's buildArguments variable to dotnetBuildOpts; Azure
  Pipelines exposes variables as environment variables and the dotnet CLI
  injects BUILDARGUMENTS into dotnet build.
Pre-emptively align this PR with the review feedback already addressed
lower in the stack, so the same comments aren't raised again.

- Reference the split download-driver-signing-key-step.yml and
  download-test-signing-key-step.yml templates instead of the removed
  download-assembly-signing-key.yml.
- Quote SigningKeyPath and TestSigningKeyPath to tolerate whitespace in
  the secure file paths.
- Fold the driver key download into the existing signing conditional in
  the pack job, removing the duplicated conditional.
- Use positive referenceType comparisons (eq 'Package').
- Drop the isInternalBuild parameter defaults; every caller already
  passes it explicitly.
- Normalize the BuildNumber/FileVersion note across all pack branches.
- Restore an accidentally dropped blank line in Azure.Test.csproj.
Copilot AI balanced review requested due to automatic review settings September 10, 2026 12:40
@github-project-automation github-project-automation Bot moved this to To triage in SqlClient Board Sep 10, 2026
@paulmedynski
paulmedynski added this pull request to stack #4671 September 10, 2026 12:45

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.

🟡 Changes recommended

Lazy bootstrap currently overwrites user providers and direct delegation changes the public failure contract.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Moves authentication-provider state into Abstractions, removing the reflection bridge while retaining driver-side lazy discovery.

Changes:

  • Adds the shared registry, lifecycle handling, localization, and direct public API delegation.
  • Renames the driver manager to AuthenticationBootstrapper and lazily initializes providers.
  • Relocates and expands registry/bootstrapper tests.
File summaries
File Description
src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/SqlAuthenticationProviderManagerTests.cs Removes superseded manager tests.
src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/DummySqlAuthenticationProvider.cs Adds the unit-test config provider.
src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/AuthenticationBootstrapperTests.cs Tests bootstrap configuration and provider creation.
src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft.Data.SqlClient.UnitTests.csproj Copies .NET Framework test configuration.
src/Microsoft.Data.SqlClient/tests/UnitTests/app.config Configures bootstrapper test values and provider.
src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlAuthenticationProviderManagerTests.cs Removes relocated functional tests.
src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.FunctionalTests.csproj Removes obsolete config copying.
src/Microsoft.Data.SqlClient/tests/FunctionalTests/DataCommon/DummySqlAuthenticationProvider.cs Removes relocated dummy provider.
src/Microsoft.Data.SqlClient/tests/FunctionalTests/app.config Removes relocated authentication configuration.
src/Microsoft.Data.SqlClient/tests/FunctionalTests/AADAuthenticationTests.cs Removes relocated provider-registration test.
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs Triggers lazy bootstrap before provider lookup.
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AuthenticationBootstrapper.cs Retains configuration and Azure discovery in the driver.
src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.cs Clarifies reference-assembly nullable conventions.
src/Microsoft.Data.SqlClient.Extensions/Azure/test/WamBrokerTests.cs Removes a global registry test.
src/Microsoft.Data.SqlClient.Extensions/Azure/test/SqlAuthenticationProviderGlobalCollection.cs Renames the global-state test collection.
src/Microsoft.Data.SqlClient.Extensions/Azure/test/DefaultAuthProviderTests.cs Removes superseded bootstrap coverage.
src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj Updates test signing configuration.
src/Microsoft.Data.SqlClient.Extensions/Azure/test/AuthenticationBootstrapperTests.cs Tests real Azure-provider construction.
src/Microsoft.Data.SqlClient.Extensions/Azure/test/AuthenticationBootstrapperGlobalTests.cs Tests global Azure-provider bootstrap.
src/Microsoft.Data.SqlClient.Extensions/Azure/test/AADAuthenticationTests.cs Uses the renamed global collection.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/SqlAuthenticationProviderTest.cs Verifies direct shared-registry delegation.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/AuthenticationProviderRegistryTest.cs Adds comprehensive registry tests.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.zh-Hant.resx Adds Traditional Chinese error text.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.zh-Hans.resx Adds Simplified Chinese error text.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.tr.resx Adds Turkish error text.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.ru.resx Adds Russian error text.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.resx Adds the invariant error resource.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.pt-BR.resx Adds Brazilian Portuguese error text.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.pl.resx Adds Polish error text.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.ko.resx Adds Korean error text.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.ja.resx Adds Japanese error text.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.it.resx Adds Italian error text.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.fr.resx Adds French error text.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.es.resx Adds Spanish error text.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.Designer.cs Adds strongly typed resource access.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.de.resx Adds German error text.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.cs.resx Adds Czech error text.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs Deletes the reflection bridge.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.cs Delegates directly to the registry.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/IsExternalInit.cs Adds an older-target compiler polyfill.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/AuthenticationProviderRegistry.cs Implements shared provider storage and precedence.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj Grants driver and test internal access.
src/Microsoft.Data.SqlClient.Extensions/Abstractions/doc/SqlAuthenticationProvider.xml Updates registry and lifecycle documentation.
Review details

Files not reviewed (1)

  • src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.Designer.cs: Generated file

Suppressed comments (1)

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AuthenticationBootstrapper.cs:361

  • These calls install the Azure provider with the normal replacement API, so a custom provider registered by the application before its first AD connection is replaced during lazy bootstrap. That reverses the previous ordering (bootstrap first, then user registration) and contradicts the comment that defaults only fill missing methods. Add an atomic “set if absent” registry operation for Azure defaults, while retaining SetPermanentProvider for app.config entries.
  • Files reviewed: 42/43 changed files
  • Comments generated: 6
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +179 to +182
internal void SetPermanentProvider(SqlAuthenticationMethod authenticationMethod, SqlAuthenticationProvider provider)
{
_providers[authenticationMethod] = new ProviderEntry(provider, IsPermanent: true);
}
Comment on lines 31 to +35
public static bool SetProvider(
SqlAuthenticationMethod authenticationMethod,
SqlAuthenticationProvider provider)
{
return Internal.SetProvider(authenticationMethod, provider);
return AuthenticationProviderRegistry.Instance.SetProvider(authenticationMethod, provider);
Comment on lines +29 to +33
// Verify that the bootstrapper installs the Azure auth provider for all AAD/Entra
// authentication methods, and not for any other methods.
//
// This project configures neither applicationClientId nor useWamBroker (it has no app.config
// overrides), so the bootstrapper constructs the Azure extension's
Comment on lines +49 to +52
// No config (applicationClientId and useWamBroker both unset) -> parameterless ctor -> the
// first-party id, which enables WAM broker.
[Fact]
public void CreateAzureProvider_NoConfig_UsesParameterlessCtor()
Comment on lines +23 to +28
<!-- Strong name signing ============================================= -->
<!-- When a test signing key is provided, sign the test assembly so IVT from signed source works. -->
<PropertyGroup Condition="'$(TestSigningKeyPath)' != ''">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(TestSigningKeyPath)</AssemblyOriginatorKeyFile>
</PropertyGroup>
Comment on lines +110 to +111
[Fact]
public void CreateAzureAuthenticationProvider_NeitherConfigured_UsesParameterlessCtor()
The public SqlAuthenticationProvider.GetProvider/SetProvider methods lived in
the Abstractions package but the registry state they mutate lived in
Microsoft.Data.SqlClient.  Because the dependency arrow points
SqlClient -> Abstractions, the only way to reach the registry from Abstractions
was reflection: SqlAuthenticationProvider.Internal used Assembly.Load and
MethodInfo.Invoke to call into the internal SqlAuthenticationProviderManager.

Move the registry state down into Abstractions, the layer both assemblies
already share, so both sides call it directly:

- Add AuthenticationProviderRegistry (internal) to Abstractions.  It owns the
  ConcurrentDictionary keyed by SqlAuthenticationMethod, the IsSupported
  enforcement, the BeforeLoad/BeforeUnload callbacks, and the permanent
  (application-specified) provider precedence rule.
- Delete SqlAuthenticationProvider.Internal.cs.  GetProvider/SetProvider now
  call the registry directly.  Their signatures are unchanged.
- Split SqlAuthenticationProviderManager into AuthenticationBootstrapper, which
  stays in the driver and keeps the app.config parsing and Azure extension
  discovery.  It seeds the shared registry through SetPermanentProvider.
- Bootstrap lazily from SqlConnectionInternal on the federated auth path
  instead of eagerly from a static constructor, so the Azure extension is only
  loaded when a connection actually authenticates.
- Grant InternalsVisibleTo to Microsoft.Data.SqlClient (signed and unsigned)
  solely so the bootstrapper can seed permanent providers; the general get/set
  path uses the public API.
- Add localized Strings resources to Abstractions for the unsupported-method
  error that previously came from SQL.UnsupportedAuthenticationByProvider.

Tests that exercise the bootstrapper move from FunctionalTests to UnitTests,
which can see driver internals, and the Azure extension tests are renamed to
match the new type names.

No public API change.
Copilot AI review requested due to automatic review settings September 10, 2026 12:47
@paulmedynski
paulmedynski force-pushed the dev/paul/auth-registry-abstractions branch from ba06a60 to 943678b Compare September 10, 2026 12:47
@paulmedynski paulmedynski added the Area\Azure Connectivity Use this to tag issues that are related to Azure connectivity. label Sep 10, 2026
@paulmedynski paulmedynski added this to the 7.1.0 milestone Sep 10, 2026
@paulmedynski paulmedynski moved this from To triage to In progress in SqlClient Board Sep 10, 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.

🔵 Needs a closer look

Lazy bootstrap can overwrite explicit providers, and the public setter now exposes previously translated exceptions.

Review details

Files not reviewed (1)

  • src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Strings.Designer.cs: Generated file

Suppressed comments (2)

src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.cs:35

  • Direct delegation changes the public API's failure semantics. The removed reflection bridge caught TargetInvocationException and returned false for manager/provider failures, including null and unsupported providers; this now exposes NullReferenceException or NotSupportedException, despite the stated compatibility goal and the XML contract documenting a false result rather than exceptions. Preserve exception-to-false translation at this public boundary and add public-API regression tests.
        return AuthenticationProviderRegistry.Instance.SetProvider(authenticationMethod, provider);

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AuthenticationBootstrapper.cs:357

  • These calls replace existing overridable entries rather than installing defaults only. With lazy bootstrap, the documented pattern of calling SqlAuthenticationProvider.SetProvider(...) before Open() first stores the custom provider, then Bootstrap() replaces it with the Azure provider. Previously bootstrap completed before the public set call, so the custom provider won. Add an atomic default-only/TryAdd registry operation and use it for every Azure method, with a regression test for registration before first authentication.
  • Files reviewed: 41/42 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@cheenamalhotra cheenamalhotra modified the milestones: 7.1.0, 8.0.0-preview1 Sep 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area\Azure Connectivity Use this to tag issues that are related to Azure connectivity.

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

3 participants