From 3409d58834ddc6bc38a2d89c854f3eaa6c3b07a0 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Mon, 16 Nov 2020 17:28:57 -0800 Subject: [PATCH 1/2] Introduce new API to clear Public Client Application instances holding User Token Cache --- .../ActiveDirectoryAuthenticationProvider.xml | 3 +++ .../netcore/ref/Microsoft.Data.SqlClient.cs | 2 ++ .../netfx/ref/Microsoft.Data.SqlClient.cs | 2 ++ .../ActiveDirectoryAuthenticationProvider.cs | 13 +++++++++++-- .../SQL/ConnectivityTests/AADConnectionTest.cs | 3 +++ 5 files changed, 21 insertions(+), 2 deletions(-) diff --git a/doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml b/doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml index 990c162acb..fe7f19ce2c 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml @@ -40,6 +40,9 @@ Acquires a security token from the authority. Represents an asynchronous operation that returns the authentication token. + + Clears cached instances of Public Client Application maintained by driver to access cached tokens from underlying token provider library. + The callback method to be used with 'Active Directory Device Code Flow' authentication. Sets the callback method, overriding the default implementation that processes the result for 'Active Directory Device Code Flow' authentication. diff --git a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs index c528e8b800..3cf24e9810 100644 --- a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs +++ b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs @@ -37,6 +37,8 @@ public sealed partial class ActiveDirectoryAuthenticationProvider : SqlAuthentic public ActiveDirectoryAuthenticationProvider() { } /// public ActiveDirectoryAuthenticationProvider(string applicationClientId) { } + /// + public static void ClearUserTokenCache() { } /// public ActiveDirectoryAuthenticationProvider(System.Func deviceCodeFlowCallbackMethod, string applicationClientId = null) { } /// diff --git a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs index 664215e020..9192733060 100644 --- a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs +++ b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs @@ -42,6 +42,8 @@ public sealed class ActiveDirectoryAuthenticationProvider : SqlAuthenticationPro public ActiveDirectoryAuthenticationProvider() { } /// public ActiveDirectoryAuthenticationProvider(string applicationClientId) { } + /// + public static void ClearUserTokenCache() { } /// public ActiveDirectoryAuthenticationProvider(System.Func deviceCodeFlowCallbackMethod, string applicationClientId = null) { } /// diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs index 2421511e62..29500ef5b4 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs @@ -47,6 +47,15 @@ public ActiveDirectoryAuthenticationProvider(Func device SetDeviceCodeFlowCallback(deviceCodeFlowCallbackMethod); } + /// + public static void ClearUserTokenCache() + { + if (!s_pcaMap.IsEmpty) + { + s_pcaMap.Clear(); + } + } + /// public void SetDeviceCodeFlowCallback(Func deviceCodeFlowCallbackMethod) => _deviceCodeFlowCallback = deviceCodeFlowCallbackMethod; @@ -190,8 +199,8 @@ public override Task AcquireTokenAsync(SqlAuthentication } catch (MsalUiRequiredException) { - // An 'MsalUiRequiredException' is thrown in the case where an interaction is required with the end user of the application, - // for instance, if no refresh token was in the cache, or the user needs to consent, or re-sign-in (for instance if the password expired), + // An 'MsalUiRequiredException' is thrown in the case where an interaction is required with the end user of the application, + // for instance, if no refresh token was in the cache, or the user needs to consent, or re-sign-in (for instance if the password expired), // or the user needs to perform two factor authentication. result = await AcquireTokenInteractiveDeviceFlowAsync(app, scopes, parameters.ConnectionId, parameters.UserId, parameters.AuthenticationMethod); SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token (interactive) for {0} auth mode. Expiry Time: {1}", parameters.AuthenticationMethod, result.ExpiresOn); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs index e8396b0b4c..d823c05b87 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs @@ -171,9 +171,12 @@ public static void AADPasswordWithWrongPassword() [ConditionalFact(nameof(IsAADConnStringsSetup))] public static void GetAccessTokenByPasswordTest() { + // Clear token cache for code coverage. + ActiveDirectoryAuthenticationProvider.ClearUserTokenCache(); using (SqlConnection connection = new SqlConnection(DataTestUtility.AADPasswordConnectionString)) { connection.Open(); + Assert.True(connection.State == System.Data.ConnectionState.Open); } } From 8b8151bc30c4ed87145a71099af0b4ed9b0ee829 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Tue, 17 Nov 2020 10:29:24 -0800 Subject: [PATCH 2/2] Update doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml Co-authored-by: David Engel --- .../ActiveDirectoryAuthenticationProvider.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml b/doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml index fe7f19ce2c..d3d6322a1b 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml @@ -41,7 +41,8 @@ Represents an asynchronous operation that returns the authentication token. - Clears cached instances of Public Client Application maintained by driver to access cached tokens from underlying token provider library. + Clears cached user tokens from the token provider. + This will cause interactive authentication prompts to appear again if tokens were previously being obtained from the cache. The callback method to be used with 'Active Directory Device Code Flow' authentication.