From 7a08f8de39849413e778ab02892682dbbee032f3 Mon Sep 17 00:00:00 2001 From: David Engel Date: Fri, 6 Sep 2024 09:50:30 -0700 Subject: [PATCH] Sync sample changes into snippet doc --- .../SqlAuthenticationProvider.xml | 59 ++++++++++++------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationProvider.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationProvider.xml index 9b6b8699e6..1a78ceec05 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationProvider.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationProvider.xml @@ -9,10 +9,12 @@ The following example demonstrates implementing a custom SqlAuthenticationProvider and providing the same to SqlClient for overriding Device Code Flow authentication mode: using System; + using System.Collections.Generic; + using System.Linq; using System.Threading.Tasks; - using Microsoft.Identity.Client; using Microsoft.Data.SqlClient; - + using Microsoft.Identity.Client; + namespace CustomAuthenticationProviderExamples { /// <summary> @@ -21,35 +23,52 @@ /// </summary> public class CustomDeviceCodeFlowAzureAuthenticationProvider : SqlAuthenticationProvider { + private const string clientId = "my-client-id"; + private const string clientName = "My Application Name"; + private const string s_defaultScopeSuffix = "/.default"; + + // Maintain a copy of the PublicClientApplication object to cache the underlying access tokens it provides + private static IPublicClientApplication pcApplication; + public override async Task<SqlAuthenticationToken> AcquireTokenAsync(SqlAuthenticationParameters parameters) { - string clientId = "my-client-id"; - string clientName = "My Application Name"; - string s_defaultScopeSuffix = "/.default"; - string[] scopes = new string[] { parameters.Resource.EndsWith(s_defaultScopeSuffix) ? parameters.Resource : parameters.Resource + s_defaultScopeSuffix }; - - IPublicClientApplication app = PublicClientApplicationBuilder.Create(clientId) - .WithAuthority(parameters.Authority) - .WithClientName(clientName) - .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient") + + IPublicClientApplication app = pcApplication; + if (app == null) + { + pcApplication = app = PublicClientApplicationBuilder.Create(clientId) + .WithAuthority(parameters.Authority) + .WithClientName(clientName) + .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient") .Build(); - - AuthenticationResult result = await app.AcquireTokenWithDeviceCode(scopes, - deviceCodeResult => CustomDeviceFlowCallback(deviceCodeResult)).ExecuteAsync(); + } + + AuthenticationResult result; + + try + { + IEnumerable<IAccount> accounts = await app.GetAccountsAsync(); + result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync(); + } + catch (MsalUiRequiredException) + { + result = await app.AcquireTokenWithDeviceCode(scopes, + deviceCodeResult => CustomDeviceFlowCallback(deviceCodeResult)).ExecuteAsync(); + } + return new SqlAuthenticationToken(result.AccessToken, result.ExpiresOn); } - - public override bool IsSupported(SqlAuthenticationMethod authenticationMethod) => - authenticationMethod.Equals(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow); - - private Task CustomDeviceFlowCallback(DeviceCodeResult result) + + public override bool IsSupported(SqlAuthenticationMethod authenticationMethod) => authenticationMethod.Equals(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow); + + private static Task<int> CustomDeviceFlowCallback(DeviceCodeResult result) { Console.WriteLine(result.Message); return Task.FromResult(0); } } - + public class Program { public static void Main()