Skip to content

Commit f19cc8f

Browse files
Introduce new API to clear global Public Client Application instances holding User Token Cache (#800)
* Introduce new API to clear Public Client Application instances holding User Token Cache * Update doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml Co-authored-by: David Engel <[email protected]> Co-authored-by: David Engel <[email protected]>
1 parent 5ebb548 commit f19cc8f

File tree

5 files changed

+22
-2
lines changed

5 files changed

+22
-2
lines changed

doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@
4040
<summary>Acquires a security token from the authority.</summary>
4141
<returns>Represents an asynchronous operation that returns the authentication token.</returns>
4242
</AcquireTokenAsync>
43+
<ClearUserTokenCache>
44+
<summary>Clears cached user tokens from the token provider.</summary>
45+
<remarks>This will cause interactive authentication prompts to appear again if tokens were previously being obtained from the cache.</remarks>
46+
</ClearUserTokenCache>
4347
<SetDeviceCodeFlowCallback>
4448
<param name="deviceCodeFlowCallbackMethod">The callback method to be used with 'Active Directory Device Code Flow' authentication.</param>
4549
<summary>Sets the callback method, overriding the default implementation that processes the result for 'Active Directory Device Code Flow' authentication.</summary>

src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public sealed partial class ActiveDirectoryAuthenticationProvider : SqlAuthentic
3737
public ActiveDirectoryAuthenticationProvider() { }
3838
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/ctor2/*'/>
3939
public ActiveDirectoryAuthenticationProvider(string applicationClientId) { }
40+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/ClearUserTokenCache/*'/>
41+
public static void ClearUserTokenCache() { }
4042
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/ctor3/*'/>
4143
public ActiveDirectoryAuthenticationProvider(System.Func<Microsoft.Identity.Client.DeviceCodeResult, System.Threading.Tasks.Task> deviceCodeFlowCallbackMethod, string applicationClientId = null) { }
4244
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/AcquireTokenAsync/*'/>

src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ public sealed class ActiveDirectoryAuthenticationProvider : SqlAuthenticationPro
4242
public ActiveDirectoryAuthenticationProvider() { }
4343
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/ctor2/*'/>
4444
public ActiveDirectoryAuthenticationProvider(string applicationClientId) { }
45+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/ClearUserTokenCache/*'/>
46+
public static void ClearUserTokenCache() { }
4547
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/ctor3/*'/>
4648
public ActiveDirectoryAuthenticationProvider(System.Func<Microsoft.Identity.Client.DeviceCodeResult, System.Threading.Tasks.Task> deviceCodeFlowCallbackMethod, string applicationClientId = null) { }
4749
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/AcquireTokenAsync/*'/>

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ public ActiveDirectoryAuthenticationProvider(Func<DeviceCodeResult, Task> device
4747
SetDeviceCodeFlowCallback(deviceCodeFlowCallbackMethod);
4848
}
4949

50+
/// <include file='../../../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/ClearUserTokenCache/*'/>
51+
public static void ClearUserTokenCache()
52+
{
53+
if (!s_pcaMap.IsEmpty)
54+
{
55+
s_pcaMap.Clear();
56+
}
57+
}
58+
5059
/// <include file='../../../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/SetDeviceCodeFlowCallback/*'/>
5160
public void SetDeviceCodeFlowCallback(Func<DeviceCodeResult, Task> deviceCodeFlowCallbackMethod) => _deviceCodeFlowCallback = deviceCodeFlowCallbackMethod;
5261

@@ -190,8 +199,8 @@ public override Task<SqlAuthenticationToken> AcquireTokenAsync(SqlAuthentication
190199
}
191200
catch (MsalUiRequiredException)
192201
{
193-
// An 'MsalUiRequiredException' is thrown in the case where an interaction is required with the end user of the application,
194-
// 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),
202+
// An 'MsalUiRequiredException' is thrown in the case where an interaction is required with the end user of the application,
203+
// 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),
195204
// or the user needs to perform two factor authentication.
196205
result = await AcquireTokenInteractiveDeviceFlowAsync(app, scopes, parameters.ConnectionId, parameters.UserId, parameters.AuthenticationMethod);
197206
SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token (interactive) for {0} auth mode. Expiry Time: {1}", parameters.AuthenticationMethod, result.ExpiresOn);

src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,12 @@ public static void AADPasswordWithWrongPassword()
171171
[ConditionalFact(nameof(IsAADConnStringsSetup))]
172172
public static void GetAccessTokenByPasswordTest()
173173
{
174+
// Clear token cache for code coverage.
175+
ActiveDirectoryAuthenticationProvider.ClearUserTokenCache();
174176
using (SqlConnection connection = new SqlConnection(DataTestUtility.AADPasswordConnectionString))
175177
{
176178
connection.Open();
179+
Assert.True(connection.State == System.Data.ConnectionState.Open);
177180
}
178181
}
179182

0 commit comments

Comments
 (0)