Skip to content

Enable WAM Broker support for Entra ID Auth modes#4288

Open
cheenamalhotra wants to merge 26 commits into
mainfrom
dev/cheena/entra-wam-broker
Open

Enable WAM Broker support for Entra ID Auth modes#4288
cheenamalhotra wants to merge 26 commits into
mainfrom
dev/cheena/entra-wam-broker

Conversation

@cheenamalhotra

@cheenamalhotra cheenamalhotra commented May 14, 2026

Copy link
Copy Markdown
Member

Enable WAM Broker support for Entra ID Auth modes

Summary

Enables Windows Account Manager (WAM) broker support for interactive Entra ID authentication in Microsoft.Data.SqlClient.Extensions.Azure. WAM provides a more secure, integrated sign-in experience on Windows (single sign-on, Windows Hello, conditional access) for the following Entra ID auth modes:

  • Active Directory Integrated
  • Active Directory Password (deprecated)
  • Active Directory Interactive
  • Active Directory Device Code Flow

Behavior

  • The WAM broker is always enabled when the driver's built-in application client id is used.
  • When a custom application client id is supplied, the WAM broker is opt-in via the new useWamBroker parameter (defaults to disabled for backward compatibility).
  • On non-Windows platforms, the broker is not used; existing system-browser / device-code flows remain unchanged.

New Public APIs

Two new constructor overloads are introduced on Microsoft.Data.SqlClient.ActiveDirectoryAuthenticationProvider (in Microsoft.Data.SqlClient.Extensions.Azure). These are added as overloads — rather than adding optional parameters to the existing constructors — to preserve binary compatibility for already-compiled consumers:

// New: application client id + WAM broker toggle
public ActiveDirectoryAuthenticationProvider(
    string applicationClientId,
    bool useWamBroker);

// New: device code flow callback + application client id + WAM broker toggle
public ActiveDirectoryAuthenticationProvider(
    Func<DeviceCodeResult, Task> deviceCodeFlowCallbackMethod,
    string? applicationClientId,
    bool useWamBroker);

Existing constructors are unchanged and remain fully source- and binary-compatible:

public ActiveDirectoryAuthenticationProvider();
public ActiveDirectoryAuthenticationProvider(string applicationClientId);
public ActiveDirectoryAuthenticationProvider(
    Func<DeviceCodeResult, Task> deviceCodeFlowCallbackMethod,
    string? applicationClientId = null);

Usage

// Custom application client id, opting into the WAM broker on Windows
var provider = new ActiveDirectoryAuthenticationProvider("<application_client_id>", useWamBroker: true);
SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, provider);

Changes

  • Added WAM broker wiring and Windows-specific parent-window handling (ActiveDirectoryAuthenticationProvider.Windows.cs, new Interop.GetAncestor / Interop.GetConsoleWindow).
  • Updated redirect URI handling for WAM broker (Windows) and system browser (Unix).
  • Added the two new constructor overloads.
  • Updated XML docs/snippets to clarify WAM broker behavior and defaults.
  • Added WamBrokerTests.cs covering built-in vs. custom client id behavior with useWamBroker true/false.

Testing

  • Unit tests added (WamBrokerTests.cs)
  • Public API changes documented (doc XML + snippets)
  • No breaking changes (new overloads preserve binary compatibility)

Copilot AI review requested due to automatic review settings May 14, 2026 02:31
@github-project-automation github-project-automation Bot moved this to To triage in SqlClient Board May 14, 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.

Pull request overview

This PR adds WAM broker support to the Azure extension authentication provider for Entra ID public-client authentication flows on Windows.

Changes:

  • Adds Microsoft.Identity.Client.Broker dependency and broker configuration during PCA creation.
  • Adds parent-window callback API and Windows interop helpers for WAM prompt parenting.
  • Adds basic tests and a draft feature spec for WAM broker support.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
Directory.Packages.props Adds centralized MSAL broker package version.
src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj References the broker package from the Azure extension.
src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs Makes the provider partial, adds parent-window callback API, and configures WAM broker on Windows.
src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.Windows.cs Adds Windows-specific parent-window discovery for broker UI.
src/Microsoft.Data.SqlClient.Extensions/Azure/src/Interop/Interop.GetAncestor.cs Adds user32.GetAncestor interop helper.
src/Microsoft.Data.SqlClient.Extensions/Azure/src/Interop/Interop.GetConsoleWindow.cs Adds kernel32.GetConsoleWindow interop helper.
src/Microsoft.Data.SqlClient.Extensions/Azure/test/WamBrokerTests.cs Adds basic tests for the new parent-window setter.
specs/002-wam-broker/spec.md Adds the draft WAM broker feature specification.
Comments suppressed due to low confidence (5)

src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs:766

  • The parent-window delegate is captured on the cached PublicClientApplication, but the static PCA cache key does not include the new SetParentActivityOrWindow callback. A later provider instance with the same authority/client/redirect can reuse an app built with an earlier provider's delegate, causing WAM prompts to be parented to the wrong window (or to ignore the later callback). Include the callback identity in the cache key or avoid capturing provider instance state in the cached app.
                builder.WithParentActivityOrWindow(GetBrokerParentWindow);
            }
            #else
            builder.WithParentActivityOrWindow(GetBrokerParentWindow);

src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs:752

  • The tests added for this feature only exercise the setter and do not verify that Windows PCA construction actually enables the broker or wires the parent-window callback. Please add unit coverage around CreateClientAppInstance (or an observable wrapper) so regressions in the WAM configuration are caught without relying solely on manual integration testing.
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            builder.WithBroker(new BrokerOptions(BrokerOptions.OperatingSystems.Windows));

specs/002-wam-broker/spec.md:70

  • This API description says Func can return IWin32Window, but the implementation only accepts IntPtr from this callback and silently ignores any other object type before falling back to console detection. Please either document only the supported return type or handle IWin32Window here as described.
        // Cross-platform API to set the parent window/activity for WAM dialog
        // On Windows: accepts IntPtr (window handle) or IWin32Window via Func<object>
        // On Unix: no-op (WAM not available)
        public void SetParentActivityOrWindow(Func<object> parentActivityOrWindowFunc);
    

    specs/002-wam-broker/spec.md:131

    • This rollout note is inaccurate: SetIWin32WindowFunc is not changed to delegate to SetParentActivityOrWindow; it still stores a separate _iWin32WindowFunc and the new callback is independent. Please update the spec or implementation so consumers and maintainers do not rely on a delegation behavior that is not present.
    - WAM broker is **always enabled** on Windows when using PCA flows
    - No opt-in connection string keyword needed (aligns with MSAL PCA compliance requirements)
    - Existing `SetIWin32WindowFunc` remains as a backward-compatible API on .NET Framework, delegating to `SetParentActivityOrWindow`
    

    src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs:749

    • This comment overstates the behavior: the code still uses AcquireTokenByIntegratedWindowsAuth, AcquireTokenByUsernamePassword, and AcquireTokenWithDeviceCode for those modes, so broker configuration does not make every supported authentication mode a WAM flow. Please narrow the comment to the modes MSAL will actually broker or update the acquisition paths accordingly.
            // Enable WAM broker on Windows for all supported authentication modes.
            // The broker provides enhanced security by enabling device-based Conditional Access
            // policies through the Windows Account Manager (WAM).
    

Comment thread specs/002-wam-broker/spec.md Outdated
Copilot AI review requested due to automatic review settings June 6, 2026 03:15

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 17 out of 18 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • doc/apps/AzureSqlConnector/MainForm.Designer.cs: Language not supported
Comments suppressed due to low confidence (1)

doc/apps/AzureSqlConnector/README.md:110

  • The last two dotnet run lines appear duplicated and are not formatted as part of the Notes list or a code block. This looks like leftover copy/paste noise and should be removed (or moved into the earlier Build & Run section as a single example).
  developer overrides).
- This is a sample / diagnostic tool, **not** a product. It does not persist credentials.
dotnet run --project .\doc\apps\AzureSqlConnector\AzureSqlConnector.csproj
dotnet run --project .\doc\apps\AzureSqlConnector\AzureSqlConnector.csproj

Comment thread doc/apps/AzureSqlConnector/README.md
Comment thread doc/apps/AzureSqlConnector/MainForm.cs
Comment thread doc/apps/AzureSqlConnector/MainForm.cs Outdated
Copilot AI review requested due to automatic review settings June 6, 2026 03:36
@cheenamalhotra cheenamalhotra added this to the 7.1.0-preview2 milestone Jun 6, 2026
@cheenamalhotra cheenamalhotra added the Hotfix 7.0.2 PRs targeting main that should be backported to release/7.0 for the 7.0.2 release. label Jun 6, 2026
@cheenamalhotra cheenamalhotra moved this from To triage to In progress in SqlClient Board Jun 6, 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.

Pull request overview

Copilot reviewed 17 out of 18 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • doc/apps/AzureSqlConnector/MainForm.Designer.cs: Language not supported

Comment thread doc/apps/AzureSqlConnector/README.md Outdated
Copilot AI review requested due to automatic review settings June 6, 2026 03: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.

Pull request overview

Copilot reviewed 17 out of 18 changed files in this pull request and generated 6 comments.

Files not reviewed (1)
  • doc/apps/AzureSqlConnector/MainForm.Designer.cs: Language not supported
Comments suppressed due to low confidence (2)

doc/apps/AzureSqlConnector/README.md:109

  • These two trailing dotnet run lines are duplicated and not formatted as a code block; the build/run instructions already appear earlier in the README.
dotnet run --project .\doc\apps\AzureSqlConnector\AzureSqlConnector.csproj

specs/002-wam-broker/spec.md:132

  • The spec claims SetIWin32WindowFunc delegates to SetParentActivityOrWindow, but the current code keeps SetIWin32WindowFunc as a separate setting. Either implement that delegation or update this statement to avoid promising behavior that doesn't exist.
- WAM broker is **always enabled** on Windows when using PCA flows
- No opt-in connection string keyword needed (aligns with MSAL PCA compliance requirements)
- Existing `SetIWin32WindowFunc` remains as a backward-compatible API on .NET Framework, delegating to `SetParentActivityOrWindow`

Comment thread doc/apps/AzureSqlConnector/MainForm.cs
Comment thread doc/apps/AzureSqlConnector/MainForm.cs Outdated
Comment thread specs/002-wam-broker/spec.md Outdated
Comment thread specs/002-wam-broker/spec.md Outdated
Copilot AI review requested due to automatic review settings June 6, 2026 03:56

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 17 out of 18 changed files in this pull request and generated 4 comments.

Files not reviewed (1)
  • doc/apps/AzureSqlConnector/MainForm.Designer.cs: Language not supported

Comment thread specs/002-wam-broker/spec.md Outdated
Comment thread doc/apps/AzureSqlConnector/README.md Outdated
Comment thread doc/apps/AzureSqlConnector/MainForm.cs

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 21 out of 22 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • doc/apps/AzureSqlConnector/MainForm.Designer.cs: Language not supported

Co-authored-by: cheenamalhotra <13396919+cheenamalhotra@users.noreply.github.com>
@codecov

codecov Bot commented Jun 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 50.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.16%. Comparing base (5ac26c9) to head (5683852).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
...Data/SqlClient/Connection/SqlConnectionInternal.cs 50.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4288      +/-   ##
==========================================
- Coverage   66.50%   64.16%   -2.35%     
==========================================
  Files         285      280       -5     
  Lines       43311    66162   +22851     
==========================================
+ Hits        28806    42454   +13648     
- Misses      14505    23708    +9203     
Flag Coverage Δ
CI-SqlClient ?
PR-SqlClient-Project 64.16% <50.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mdaigle mdaigle self-assigned this Jun 10, 2026
}

/// <include file='../doc/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/AcquireTokenAsync/*'/>
public override async Task<SqlAuthenticationToken> AcquireTokenAsync(SqlAuthenticationParameters parameters)

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.

What stance have you taken on synchronizing this action with the main UI thread? Will we leave it broken for UI apps?

We can pop a non-system browser window without being on the main thread, but the system browser and WAM picker I believe do require the main UI thread. We should test with winforms / VS extension / others. I previously had to expose an API to pass SynchronizationContext: https://github.com/dotnet/SqlClient/pull/3874/changes#diff-7b20b6d8d7c505871ab9d3762e51086d6848bae49bf6864f8e5b5adfc3070846R318

We should also test calling SqlConnection.Open() and OpenAsync() directly from the main thread to ensure we don't introduce any deadlock.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The sample WinForms app I added uses system browser and doesn't seem to go in a deadlock. Have you tried that?

Comment thread doc/apps/AzureSqlConnector/MainForm.cs Outdated
string serverVersion;
using (SqlConnection connection = new SqlConnection(builder.ConnectionString))
{
await connection.OpenAsync().ConfigureAwait(true);

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.

Good to see that this works. Have you tested the sync API?
Also looking for a test that covers opening on a worker thread.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Sync API works too in my sample, tested.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

it'd be good for this app to have 2 buttons, one for sync .Open and one for async. SSMS is still only using synchronous calls on the UI thread, so evidence it will work there is helpful.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

what changed in the core driver that unblocks using the synchronous SqlConnection.Open call on the UI thread? How does MSAL invoke the dialog open back to the UI thread while the driver is blocking, waiting for the token acquisition? Can you capture a call stack at the time the MSAL window is displayed during the synchronous call? I'm very curious what it looks like.

@cheenamalhotra cheenamalhotra Jun 17, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

MSAL calls WithBroker(...) and routes through Microsoft.Identity.Client.NativeInteropWAM (Microsoft.AAD.BrokerPlugin). WAM runs in a separate process. We pass a window handle via WithParentActivityOrWindow(GetParentWindow()) (resolved in ActiveDirectoryAuthenticationProvider.Windows.cs) purely so WAM can parent its dialog to our app for modality / Z-order / taskbar grouping. The dialog itself is drawn entirely by WAM in its own process; our UI thread just blocks on the WAM IPC call. No in-process message pump is required, so sync Open() on the UI thread is safe in this mode.

The stacktrace goes like this:
image.png

@paulmedynski paulmedynski 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.

Overall the changes look good. The test app is a great idea. My comments are mostly to tighten up the API and docs and add some missing test coverage.

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.

Hmm... why do we need this file at all? Who consumes this? Just curious - it's an existing problem, so not necessary to fix in this PR.

@cheenamalhotra cheenamalhotra Jun 12, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I was curious too, needs a cleanup I suppose.
This should be removed IMO - I wanted to verify before I hit the delete button.

Likewise, there are many other xml files left overs in the root doc folder that need to be cleaned up. This should be done separately.

</example>
</SetDeviceCodeFlowCallback>
<SetParentActivityOrWindowFunc>
<SetParentActivityOrWindow>

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.

Interesting - the SetParentActivityOrWindowsFunc method didn't actually exist on the class. This PR is effectively removing that imagined method, and adding the new SetParentActivityOrWindow method.

@cheenamalhotra cheenamalhotra Jun 12, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This API was introduced for .NET Standard only, but was removed when .NET Standard support was dropped I think. It is added back now for both .NET Standard and .NET Framework this time. I've changed to name to SetParentActivityOrWindowFunc again to retain Func suffix.


namespace Microsoft.Data.SqlClient;

internal static partial class Interop

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.

Missing class and field docs, explaining why this exists, how/when to use it, etc.


namespace Microsoft.Data.SqlClient;

internal static partial class Interop

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.

Missing class docs, explaining why this exists, how/when to use it, etc.


internal static partial class Interop
{
internal static partial class User32

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.

Do we typically diverge from file name == class name for these Interop things? I do like that the class name implies which Windows DLL it imports, but I'm not sure if that is worth the divergence.

{
// A custom application id without explicitly opting in must NOT enable WAM broker.
string customAppId = Guid.NewGuid().ToString();
var provider = new ActiveDirectoryAuthenticationProvider(customAppId);

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.

What if the caller supplies the SqlClient first-party app id here?

Note that this is calling a different constructor than the test on line 80, so it needs a separate test.

private static bool GetUseWamBrokerField(ActiveDirectoryAuthenticationProvider provider)
{
FieldInfo? field = typeof(ActiveDirectoryAuthenticationProvider)
.GetField("_useWamBroker", BindingFlags.Instance | BindingFlags.NonPublic);

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.

Maybe we want internal bool UseWamBroker { get; } on the provider, and then we can access it directly in these tests.

var provider = new ActiveDirectoryAuthenticationProvider(
deviceCodeFlowCallbackMethod: static _ => Task.CompletedTask,
applicationClientId: customAppId,
useWamBroker: true);

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.

Missing the case where useWamBroker is false.

// A provider created with useWamBroker=true and registered via SqlAuthenticationProvider
// must retain its WAM broker setting after registration (i.e. SetProvider must not wrap
// or replace the instance).
string customAppId = Guid.NewGuid().ToString();

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.

We should probably assert that the guid isn't the SqlClient app id. Here and elsewhere.

{
if (original is not null)
{
SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, original);

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.

I have wondered why we don't support un-setting a provider. This test has now polluted the global state if ActiveDirectoryInteractive didn't have a provider registered before.

@github-project-automation github-project-automation Bot moved this from In review to Waiting for customer in SqlClient Board Jun 11, 2026
@cheenamalhotra

Copy link
Copy Markdown
Member Author

Adding @shueybubbles for visibility on the PR.

/// connection string via <see cref="SqlConnectionStringBuilder"/>, and optionally tests
/// connectivity using <see cref="SqlConnection"/>.
/// </summary>
public partial class MainForm : Form

@shueybubbles shueybubbles Jun 12, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ainForm

the other scenario to demo in this app is a non-STA background thread calling SqlConnection.Open and using the main form's Window handle as the popup owner, particularly when that is the first call to Open so no credential has been cached.

<PackageReference Include="Microsoft.Extensions.Caching.Memory" />
<!-- Explicitly depend on the same version of Microsoft.Identity.Client as SqlClient. -->
<PackageReference Include="Microsoft.Identity.Client" />
<PackageReference Include="Microsoft.Identity.Client.Broker" />

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Microsoft.Identity.Client.Broker" /

are there new upstream dependencies this pulls in that might surprise people?

// Maintain a flag to disable WAM broker mode for backwards compatibility
// in applications using ActiveDirectoryAuthenticationProvider with custom Application Client ID.
private readonly bool _useWamBroker = false;
private const string s_wamBrokerRedirectUriPrefix = "ms-appx-web://microsoft.aad.brokerplugin/";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

private const string s_wamBrokerRedirectUriPrefi

doesn't MSAL have parameters now that build the redirect URIs for you so you don't have to do it? EG if you give it a client id and tell it to use broker, isn't there a way for the app builder to use the default redirect uri based on the client id?

Copilot AI review requested due to automatic review settings June 17, 2026 06:00

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 23 out of 25 changed files in this pull request and generated 4 comments.

Files not reviewed (2)
  • doc/apps/AzureSqlConnector/MainForm.Designer.cs: Generated file
  • doc/apps/AzureSqlConnector/MainFormWorker.Designer.cs: Generated file

Comment on lines +12 to +21
<PropertyGroup>
<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">net481;net10.0-windows</TargetFrameworks>
<TargetFramework Condition="'$(OS)' != 'Windows_NT'">net10.0-windows</TargetFramework>
<OutputType>WinExe</OutputType>
<RootNamespace>Microsoft.Data.SqlClient.Samples.AzureSqlConnector</RootNamespace>
<AssemblyName>AzureSqlConnector</AssemblyName>
<UseWindowsForms>true</UseWindowsForms>
<LangVersion>latest</LangVersion>
<Nullable>disable</Nullable>
<Platforms>AnyCPU</Platforms>
Comment thread doc/apps/AzureSqlConnector/NuGet.config Outdated
Comment thread doc/apps/AzureSqlConnector/MainForm.cs Outdated
Comment on lines +133 to +135
/// <include file='../doc/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/ctorOptions/*'/>
public ActiveDirectoryAuthenticationProvider(ProviderOptions options)
{
Copilot AI review requested due to automatic review settings June 17, 2026 06:42

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 24 out of 26 changed files in this pull request and generated 2 comments.

Files not reviewed (2)
  • doc/apps/AzureSqlConnector/MainForm.Designer.cs: Generated file
  • doc/apps/AzureSqlConnector/MainFormWorker.Designer.cs: Generated file

Comment on lines +857 to +861
}
#if NETFRAMEWORK
if (publicClientAppKey.IWin32WindowFunc is not null)
else if (publicClientAppKey.IWin32WindowFunc is not null)
{
// Not on Windows (shouldn't happen for NETFRAMEWORK, but be defensive).
Comment on lines +86 to +90
var provider = new ActiveDirectoryAuthenticationProvider();

Assert.True(provider.UseWamBroker,
"Default ctor must enable WAM broker (uses SqlClient first-party application id).");
}
Copilot AI review requested due to automatic review settings June 17, 2026 06:55

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 24 out of 26 changed files in this pull request and generated 2 comments.

Files not reviewed (2)
  • doc/apps/AzureSqlConnector/MainForm.Designer.cs: Generated file
  • doc/apps/AzureSqlConnector/MainFormWorker.Designer.cs: Generated file

Comment on lines +133 to 150
/// <include file='../doc/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/ctorOptions/*'/>
public ActiveDirectoryAuthenticationProvider(ProviderOptions options)
{
if (options is null)
{
_applicationClientId = applicationClientId;
throw new ArgumentNullException(nameof(options));
}

_deviceCodeFlowCallback = options.DeviceCodeFlowCallback ?? DefaultDeviceFlowCallback;
if (options.ApplicationClientId is not null)
{
_applicationClientId = options.ApplicationClientId;
}
// WAM broker mode is always enabled for the SqlClient first-party application id (its
// app registration is configured for the WAM broker redirect URI). For a caller-supplied
// application id, WAM is opt-in via ProviderOptions.UseWamBroker.
_useWamBroker = _applicationClientId == s_sqlClientApplicationId || options.UseWamBroker;
}
Comment on lines +10 to +25
// The SqlClient first-party application client id that is hard-coded in the provider.
private const string SqlClientApplicationId = "2fd908ad-0664-4344-b9be-cd3e8b574c38";

/// <summary>
/// Defensive guard: every test that uses <see cref="Guid.NewGuid"/> as a stand-in for a
/// caller-supplied application id assumes the GUID will never collide with the SqlClient
/// first-party id. This test makes that assumption explicit.
/// </summary>
[Fact]
public void Ctor_CustomAppId_GuidIsNotSqlClientAppId()
{
for (int i = 0; i < 16; i++)
{
Assert.NotEqual(SqlClientApplicationId, Guid.NewGuid().ToString());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Hotfix 7.0.2 PRs targeting main that should be backported to release/7.0 for the 7.0.2 release. Public API 🆕 Issues/PRs that introduce new APIs to the driver.

Projects

Status: Waiting for customer

Development

Successfully merging this pull request may close these issues.

8 participants