diff --git a/doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml b/doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml index 607ee31342..b66bbf809e 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml @@ -23,8 +23,16 @@ The callback method to be used by driver when performing 'Active Directory Device Code Flow' authentication. - Set's callback method that overrides driver's default implementation to process result when performing 'Active Directory Device Code Flow' authentication. + Sets callback method that overrides driver's default implementation to process result when performing 'Active Directory Device Code Flow' authentication. + + A function to return the current window or the parent as an object, in order to be used from shared NetStandard assemblies. + Sets a reference to the ViewController (if using Xamarin.iOS), Activity (if using Xamarin.Android) IWin32Window or IntPtr (if using .Net Framework). Used for invoking the browser for Active Directory Interactive authentication. + + + Customer implementation for the Web UI + Sets a custom Web UI that will let the user sign-in with Azure AD, present consent if needed, and get back the authorization code. Applicable when working with Active Directory Interactive authentication. + The authentication method. This method is called immediately before the provider is added to SQL drivers registry. 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 6589f9a077..9a862794f4 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Identity.Client; +using Microsoft.Identity.Client.Extensibility; namespace Microsoft.Data.SqlClient { @@ -18,6 +19,8 @@ public sealed class ActiveDirectoryAuthenticationProvider : SqlAuthenticationPro private readonly string _type = typeof(ActiveDirectoryAuthenticationProvider).Name; private readonly SqlClientLogger _logger = new SqlClientLogger(); private Func _deviceCodeFlowCallback; + private Func parentActivityOrWindowFunc = null; + private ICustomWebUi customWebUI = null; /// public ActiveDirectoryAuthenticationProvider() => new ActiveDirectoryAuthenticationProvider(DefaultDeviceFlowCallback); @@ -63,12 +66,30 @@ public ActiveDirectoryAuthenticationProvider(Func device redirectURI = "http://localhost"; } #endif - IPublicClientApplication app = PublicClientApplicationBuilder.Create(ActiveDirectoryAuthentication.AdoClientId) + IPublicClientApplication app; + + if (parentActivityOrWindowFunc != null) + { + app = PublicClientApplicationBuilder.Create(ActiveDirectoryAuthentication.AdoClientId) .WithAuthority(parameters.Authority) .WithClientName(Common.DbConnectionStringDefaults.ApplicationName) .WithClientVersion(Common.ADP.GetAssemblyVersion().ToString()) .WithRedirectUri(redirectURI) +#if !netcoreapp + .WithParentActivityOrWindow(parentActivityOrWindowFunc) +#endif .Build(); + } + else + { + + app = PublicClientApplicationBuilder.Create(ActiveDirectoryAuthentication.AdoClientId) + .WithAuthority(parameters.Authority) + .WithClientName(Common.DbConnectionStringDefaults.ApplicationName) + .WithClientVersion(Common.ADP.GetAssemblyVersion().ToString()) + .WithRedirectUri(redirectURI) + .Build(); + } if (parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryIntegrated) { @@ -134,6 +155,7 @@ public ActiveDirectoryAuthenticationProvider(Func device return new SqlAuthenticationToken(result.AccessToken, result.ExpiresOn); }); + private async Task AcquireTokenInteractiveDeviceFlow(IPublicClientApplication app, string[] scopes, Guid connectionId, string userId, SqlAuthenticationMethod authenticationMethod) { @@ -154,7 +176,16 @@ public ActiveDirectoryAuthenticationProvider(Func device { if (authenticationMethod == SqlAuthenticationMethod.ActiveDirectoryInteractive) { - return await app.AcquireTokenInteractive(scopes) + if (customWebUI != null) + { + return await app.AcquireTokenInteractive(scopes) + .WithCorrelationId(connectionId) + .WithCustomWebUi(customWebUI) + .WithLoginHint(userId) + .ExecuteAsync(cts.Token); + } + else + { /* * We will use the MSAL Embedded or System web browser which changes by Default in MSAL according to this table: * @@ -172,10 +203,11 @@ public ActiveDirectoryAuthenticationProvider(Func device * * https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/MSAL.NET-uses-web-browser#at-a-glance */ - //.WithUseEmbeddedWebView(true) - .WithCorrelationId(connectionId) - .WithLoginHint(userId) - .ExecuteAsync(cts.Token); + return await app.AcquireTokenInteractive(scopes) + .WithCorrelationId(connectionId) + .WithLoginHint(userId) + .ExecuteAsync(cts.Token); + } } else { @@ -211,6 +243,19 @@ private Task DefaultDeviceFlowCallback(DeviceCodeResult result) /// public void SetDeviceCodeFlowCallback(Func deviceCodeFlowCallbackMethod) => _deviceCodeFlowCallback = deviceCodeFlowCallbackMethod; + /// + public void SetParentActivityOrWindowFunc(Func parentActivityOrWindowFunc) + { + this.parentActivityOrWindowFunc = parentActivityOrWindowFunc; + } + + /// + public void SetCustomWebUI(ICustomWebUi customWebUi) + { + + customWebUI = customWebUi; + } + /// public override bool IsSupported(SqlAuthenticationMethod authentication) {