Skip to content

Fix non-actionable error when Active Directory authentication provider is missing#4035

Closed
apoorvdeshmukh wants to merge 4 commits intomainfrom
dev/ad/3962
Closed

Fix non-actionable error when Active Directory authentication provider is missing#4035
apoorvdeshmukh wants to merge 4 commits intomainfrom
dev/ad/3962

Conversation

@apoorvdeshmukh
Copy link
Contributor

Description

Fixes #3962.

Issues

#3962

Testing

Unit tests added (SqlUtilErrorMessageTests.cs) covering:
AD auth methods return the actionable message with package install instructions
Non-AD auth methods return the existing generic message
All 9 Active Directory authentication modes validated via parameterized test

Guidelines

Please review the contribution guidelines before submitting a pull request:

@apoorvdeshmukh apoorvdeshmukh requested a review from a team as a code owner March 11, 2026 20:09
Copilot AI review requested due to automatic review settings March 11, 2026 20:09
@github-project-automation github-project-automation bot moved this to To triage in SqlClient Board Mar 11, 2026
@apoorvdeshmukh apoorvdeshmukh added this to the 7.0.0 milestone Mar 11, 2026
Copy link
Contributor

Copilot AI left a comment

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 improves the developer experience when Active Directory authentication is requested but the Azure authentication provider isn’t available, by throwing a more actionable error that includes package install guidance.

Changes:

  • Add a dedicated localized error message for missing Active Directory auth provider with NuGet install instructions.
  • Throw the new actionable exception for Active Directory authentication methods when no provider is registered.
  • Add unit tests validating the new message for AD auth methods and preserving the generic message for non-AD methods.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/SqlUtilErrorMessageTests.cs Adds unit coverage for the new actionable AD-provider-missing error message vs. the generic message.
src/Microsoft.Data.SqlClient/src/Resources/Strings.resx Introduces a new localized string resource for the AD-provider-missing scenario.
src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs Adds the generated strongly-typed accessor for the new resource string.
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlUtil.cs Adds a new SQL.CannotFindActiveDirectoryAuthProvider(...) exception factory.
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs Switches AD auth methods to throw the new actionable exception when the provider is missing.
Files not reviewed (1)
  • src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs: Language not supported

You can also share your feedback on Copilot code review. Take the survey.

@apoorvdeshmukh apoorvdeshmukh requested review from a team and mdaigle March 11, 2026 20:45
@codecov
Copy link

codecov bot commented Mar 11, 2026

Codecov Report

❌ Patch coverage is 42.85714% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 65.04%. Comparing base (3f9246c) to head (cc10c1e).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...Data/SqlClient/Connection/SqlConnectionInternal.cs 0.00% 4 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (3f9246c) and HEAD (cc10c1e). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (3f9246c) HEAD (cc10c1e)
CI-SqlClient 1 0
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4035      +/-   ##
==========================================
- Coverage   72.87%   65.04%   -7.83%     
==========================================
  Files         287      282       -5     
  Lines       43134    66050   +22916     
==========================================
+ Hits        31432    42960   +11528     
- Misses      11702    23090   +11388     
Flag Coverage Δ
CI-SqlClient ?
PR-SqlClient-Project 65.04% <42.85%> (?)

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

☔ View full report in Codecov by Sentry.
📢 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.

Copilot AI review requested due to automatic review settings March 12, 2026 13:21
Copy link
Contributor

Copilot AI left a comment

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


You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +25 to +28
<data name="Icon1" type="System.Drawing.Icon, System.Drawing"
mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework
object]</value>
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

This PR includes unrelated whitespace/line-wrapping changes in Strings.resx (e.g., Icon1 and schema/resheader entries). These formatting-only edits add noise and increase merge-conflict risk without affecting the functional error-message change. Consider reverting the unrelated reformatting (or moving it to a dedicated PR).

Suggested change
<data name="Icon1" type="System.Drawing.Icon, System.Drawing"
mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework
object]</value>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed - I'm not sure what auto-formatting you have enabled, but I would advise disabling it all except for trimming trailing whitespace.

Comment on lines +2735 to +2738
#pragma warning disable 0618 // ActiveDirectoryPassword is obsolete
if (ConnectionOptions.Authentication >= SqlAuthenticationMethod.ActiveDirectoryPassword
&& ConnectionOptions.Authentication <= SqlAuthenticationMethod.ActiveDirectoryWorkloadIdentity)
#pragma warning restore 0618
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

The AD-auth detection relies on a numeric range comparison over SqlAuthenticationMethod values (>= ActiveDirectoryPassword and <= ActiveDirectoryWorkloadIdentity). This is brittle because it silently depends on enum value ordering/contiguity and could misclassify methods if the enum changes. Prefer an explicit switch/pattern match listing the AD methods (or a shared helper) so the intent stays correct if the enum evolves.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed - just list each method explictily here to make it obvious.

Comment on lines +2591 to +2592
<data name="SQL_CannotFindActiveDirectoryAuthProvider" xml:space="preserve">
<value>Cannot find an authentication provider for '{0}'. The 'Microsoft.Data.SqlClient.Extensions.Azure' NuGet package provides default implementations for Active Directory (Entra ID) authentication methods.</value>
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

The new message claims the Azure extensions package "provides default implementations", but it doesn't actually give install instructions (e.g., "Install/Reference the Microsoft.Data.SqlClient.Extensions.Azure package" and/or a link/command). This seems inconsistent with the PR description's claim of "package install instructions" and may still be non-actionable for users.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

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

Sure, maybe provide the URL to the nuget.org page for the package.

@paulmedynski paulmedynski self-assigned this Mar 12, 2026
Comment on lines +2735 to +2738
#pragma warning disable 0618 // ActiveDirectoryPassword is obsolete
if (ConnectionOptions.Authentication >= SqlAuthenticationMethod.ActiveDirectoryPassword
&& ConnectionOptions.Authentication <= SqlAuthenticationMethod.ActiveDirectoryWorkloadIdentity)
#pragma warning restore 0618
Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed - just list each method explictily here to make it obvious.

Copy link
Contributor

Choose a reason for hiding this comment

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

This diff is enormous. What happened?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copilot added some formatting noise which it simply could not fix.
I manually reverted changes but it's taking too long.
Raised #4046 to clean up the changes.

Comment on lines +25 to +28
<data name="Icon1" type="System.Drawing.Icon, System.Drawing"
mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework
object]</value>
Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed - I'm not sure what auto-formatting you have enabled, but I would advise disabling it all except for trimming trailing whitespace.

Comment on lines +2591 to +2592
<data name="SQL_CannotFindActiveDirectoryAuthProvider" xml:space="preserve">
<value>Cannot find an authentication provider for '{0}'. The 'Microsoft.Data.SqlClient.Extensions.Azure' NuGet package provides default implementations for Active Directory (Entra ID) authentication methods.</value>
Copy link
Contributor

Choose a reason for hiding this comment

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

Sure, maybe provide the URL to the nuget.org page for the package.

@github-project-automation github-project-automation bot moved this from To triage to In progress in SqlClient Board Mar 12, 2026

namespace Microsoft.Data.SqlClient.UnitTests
{
public class SqlUtilErrorMessageTests
Copy link
Contributor

Choose a reason for hiding this comment

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

Unit test files/classes should be the same as the class they are testing with "Tests" at the end. There is no SqlUtilErrorMessage class, so please update to correspond to the class that's actually being tested.

[Fact]
public void CannotFindAuthProvider_ReturnsGenericMessage()
{
Exception exception = global::Microsoft.Data.SqlClient.SQL.CannotFindAuthProvider("SomeCustomAuth");
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not familiar with the global:: syntax here. Can we just have a using at the top of the file and access the method like we would in the code?

[InlineData("ActiveDirectoryMSI")]
[InlineData("ActiveDirectoryDefault")]
[InlineData("ActiveDirectoryWorkloadIdentity")]
public void CannotFindActiveDirectoryAuthProvider_ContainsPackageGuidance(string authMethod)
Copy link
Contributor

Choose a reason for hiding this comment

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

Honestly, I'm not very sure of the value of these tests. They're really just testing whether the exception text returned by the exception helper is right. This doesn't really test the new behavior or the scenario that prompted the change in the first place.

Instead of testing the sqlutil class, test the SqlConnectionInternal class to make sure that if you don't have Azure package loaded, it will tell you to load Azure package. If that's not possible, consider moving the check into SqlUtil class and pass the auth method to it to decide. That could be tested via a unit test here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Indeed - these tests apear to be trying to confirm that the SqlUtil functions return ArgumentException instances with some expected text based on the English (default?) strings resources.

I'm not sure if we have any existing tests for things like this.

I'm also not sure if they will pass when the tests are run using other languages.

@apoorvdeshmukh
Copy link
Contributor Author

Closing as addressing this via #4046

@github-project-automation github-project-automation bot moved this from In progress to Done in SqlClient Board Mar 13, 2026
@apoorvdeshmukh apoorvdeshmukh deleted the dev/ad/3962 branch March 13, 2026 15:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Azure split] Non-actionable error message if only the base package is referenced

6 participants