Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<!-- MDS and AKV -->
<PackageVersion Include="Azure.Core" Version="1.49.0" />
<PackageVersion Include="Microsoft.Identity.Client" Version="4.78.0" />
<PackageVersion Include="Microsoft.Identity.Client.Broker" Version="4.78.0" />
</ItemGroup>
<!-- Published - Target Framework Specific Dependencies -->
<ItemGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net9.0'))">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
<PackageReference Include="Microsoft.Bcl.Cryptography" />
<PackageReference Include="Microsoft.Data.SqlClient.SNI.runtime" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" />
<PackageReference Include="Microsoft.Identity.Client.Broker"/>
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" />
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" />
<PackageReference Include="Microsoft.SqlServer.Server" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,7 @@
<PackageReference Include="Microsoft.Bcl.Cryptography" />
<PackageReference Include="Microsoft.Data.SqlClient.SNI.runtime" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" />
<PackageReference Include="Microsoft.Identity.Client.Broker"/>
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" />
Comment on lines 1084 to 1088
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

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

The INTERACTIVE_AUTH compilation constant is defined for Debug builds in the netfx project but is not defined in the netcore project at all. This means that interactive authentication with broker support will only work in .NET Framework Debug builds or when InteractiveAuthEnabled is explicitly set to true. The netcore project needs a similar conditional compilation setup to enable broker authentication support, otherwise the new broker authentication code will never be compiled for .NET Core/NET builds.

Copilot uses AI. Check for mistakes.
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" />
<PackageReference Include="Microsoft.SqlServer.Server" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" />
<PackageReference Include="Microsoft.Identity.Client.Broker" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" />
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" />
<PackageReference Include="System.Buffers" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'" />
<PropertyGroup Condition="$(Configuration.Contains('Debug'))">
<DefineConstants>$(DefineConstants);DEBUG;DBG;_DEBUG;_LOGGING;RESOURCE_ANNOTATION_WORK;</DefineConstants>
<DefineConstants>$(DefineConstants);DEBUG;DBG;_DEBUG;_LOGGING;RESOURCE_ANNOTATION_WORK;INTERACTIVE_AUTH;</DefineConstants>
<DebugType>Full</DebugType>
<Optimize>False</Optimize>
</PropertyGroup>
Expand All @@ -82,6 +82,11 @@
<DebugType>Pdbonly</DebugType>
<Optimize>True</Optimize>
</PropertyGroup>

<PropertyGroup Condition="'$(InteractiveAuthEnabled)'=='true'">
<DefineConstants>$(DefineConstants);INTERACTIVE_AUTH;</DefineConstants>
</PropertyGroup>

<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Configuration" />
Expand Down Expand Up @@ -1070,6 +1075,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" />
<PackageReference Include="Microsoft.Identity.Client.Broker"/>
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" />
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" />
<PackageReference Include="System.Buffers" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Runtime.InteropServices;

internal partial class Interop
{
internal partial class Kernel32
{
[DllImport("kernel32.dll")]
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

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

The GetConsoleWindow P/Invoke declaration is missing the ExactSpelling parameter. Windows API functions should typically use ExactSpelling=true to avoid unnecessary string marshaling overhead and potential issues with ANSI/Unicode name resolution. Consider adding ExactSpelling=true to the DllImport attribute.

Suggested change
[DllImport("kernel32.dll")]
[DllImport("kernel32.dll", ExactSpelling = true)]

Copilot uses AI. Check for mistakes.
internal static extern IntPtr GetConsoleWindow();
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

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

Minimise the use of unmanaged code.

Copilot uses AI. Check for mistakes.
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Runtime.InteropServices;


internal partial class Interop
{
internal partial class User32
{
internal enum GetAncestorFlags
{
GetParent = 1,
GetRoot = 2,
/// <summary>
/// Retrieves the owned root window by walking the chain of parent and owner windows returned by GetParent.
/// </summary>
GetRootOwner = 3
}

/// <summary>
/// Retrieves the handle to the ancestor of the specified window.
/// </summary>
/// <param name="hwnd">A handle to the window whose ancestor is to be retrieved.
/// If this parameter is the desktop window, the function returns NULL. </param>
/// <param name="flags">The ancestor to be retrieved.</param>
/// <returns>The return value is the handle to the ancestor window.</returns>
[DllImport("user32.dll", ExactSpelling = true)]
internal static extern IntPtr GetAncestor(IntPtr hwnd, GetAncestorFlags flags);
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

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

Minimise the use of unmanaged code.

Copilot uses AI. Check for mistakes.
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Threading;

namespace Microsoft.Data.SqlClient
{
public sealed partial class ActiveDirectoryAuthenticationProvider : SqlAuthenticationProvider
{
private Func<object> _parentActivityOrWindowFunc = null;

Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

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

The Unix implementation of ParentActivityOrWindow always returns null when _parentActivityOrWindowFunc is null, but the Windows implementation provides a fallback to GetConsoleOrTerminalWindow(). This inconsistency could lead to different behavior between platforms. Consider documenting this platform-specific behavior or ensuring consistent handling across platforms.

Suggested change
/// <summary>
/// Gets the delegate that provides the parent activity or window object for interactive authentication.
/// <para>
/// On Unix platforms, when <see cref="_parentActivityOrWindowFunc"/> is <c>null</c>, this property
/// also evaluates to <c>null</c>. Unlike the Windows implementation, there is no fallback to a
/// console or terminal window handle on Unix.
/// </para>
/// </summary>

Copilot uses AI. Check for mistakes.
private Func<object> ParentActivityOrWindow => _parentActivityOrWindowFunc;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;

namespace Microsoft.Data.SqlClient
{
public sealed partial class ActiveDirectoryAuthenticationProvider : SqlAuthenticationProvider
{
private Func<object> _parentActivityOrWindowFunc = null;

private Func<object> ParentActivityOrWindow
{
get
{
return _parentActivityOrWindowFunc != null ? _parentActivityOrWindowFunc : GetConsoleOrTerminalWindow;
}

set
{
_parentActivityOrWindowFunc = value;
}
}

#if NETFRAMEWORK
/// <include file='../../../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/SetIWin32WindowFunc/*'/>
public void SetIWin32WindowFunc(Func<System.Windows.Forms.IWin32Window> iWin32WindowFunc) => SetParentActivityOrWindow(iWin32WindowFunc);
#endif

/// <summary>
///
/// </summary>
/// <param name="parentActivityOrWindowFunc"></param>
Comment on lines +32 to +34
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

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

The SetParentActivityOrWindow method is missing documentation. Add XML documentation comments to explain the purpose of this method, the parentActivityOrWindowFunc parameter, and when this should be used in the authentication flow.

Suggested change
///
/// </summary>
/// <param name="parentActivityOrWindowFunc"></param>
/// Sets a callback that returns the parent activity or window to use for interactive authentication dialogs.
/// </summary>
/// <param name="parentActivityOrWindowFunc">
/// A delegate that returns an object representing the parent activity or window (for example,
/// a <see cref="System.Windows.Forms.IWin32Window"/> or a platform-specific window handle).
/// If this delegate is not provided, the provider falls back to using the console or terminal window handle.
/// </param>
/// <remarks>
/// Call this method before initiating an Azure Active Directory authentication flow that may display UI,
/// so that any interactive dialogs are correctly parented to the specified application window or activity.
/// This is typically used in desktop or GUI applications that host interactive authentication experiences.
/// </remarks>

Copilot uses AI. Check for mistakes.
public void SetParentActivityOrWindow(Func<object> parentActivityOrWindowFunc) => this.ParentActivityOrWindow = parentActivityOrWindowFunc;

private object GetConsoleOrTerminalWindow()
{
IntPtr consoleHandle = Interop.Kernel32.GetConsoleWindow();
IntPtr handle = Interop.User32.GetAncestor(consoleHandle, Interop.User32.GetAncestorFlags.GetRootOwner);

return handle;
}
}
}
Loading
Loading