Skip to content

Commit

Permalink
Add support for user-defined ApplicationClientId
Browse files Browse the repository at this point in the history
  • Loading branch information
cheenamalhotra committed Sep 23, 2020
1 parent 81052d6 commit 03a36c4
Show file tree
Hide file tree
Showing 12 changed files with 119 additions and 18 deletions.
Expand Up @@ -11,11 +11,18 @@
</summary>
</ctor>
<ctor2>
<param name="deviceCodeFlowCallbackMethod">The callback method to be used when performing 'Active Directory Device Code Flow' authentication.</param>
<param name="applicationClientId">Client Application Id to be used for acquiring access token for federated authentication. The driver uses it's own application client id by default.</param>
<summary>
Initializes the <see cref="T:Microsoft.Data.SqlClient.ActiveDirectoryAuthenticationProvider" /> class with the provided device code flow callback method.
Initializes the <see cref="T:Microsoft.Data.SqlClient.ActiveDirectoryAuthenticationProvider" /> class with the provided application client id.
</summary>
</ctor2>
<ctor3>
<param name="deviceCodeFlowCallbackMethod">The callback method to be used when performing 'Active Directory Device Code Flow' authentication.</param>
<param name="applicationClientId">(Optional) Client Application Id to be used for acquiring access token for federated authentication. The driver uses it's own application client id by default.</param>
<summary>
Initializes the <see cref="T:Microsoft.Data.SqlClient.ActiveDirectoryAuthenticationProvider" /> class with the provided device code flow callback method and application client id.
</summary>
</ctor3>
<AcquireTokenAsync>
<param name="parameters">The Active Directory authentication parameters passed to authentication providers.</param>
<summary>Acquires a security token from the authority.</summary>
Expand Down
Expand Up @@ -15,7 +15,6 @@ internal partial class SqlAuthenticationProviderManager

static SqlAuthenticationProviderManager()
{
var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider();
SqlAuthenticationProviderConfigurationSection configurationSection = null;

try
Expand All @@ -35,6 +34,7 @@ static SqlAuthenticationProviderManager()
}

Instance = new SqlAuthenticationProviderManager(configurationSection);
var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider(Instance._applicationClientId);
Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryIntegrated, activeDirectoryAuthProvider);
Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, activeDirectoryAuthProvider);
Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, activeDirectoryAuthProvider);
Expand All @@ -59,6 +59,24 @@ public SqlAuthenticationProviderManager(SqlAuthenticationProviderConfigurationSe
return;
}

if (!string.IsNullOrEmpty(configSection.ApplicationClientId))
{
try
{
_applicationClientId = configSection.ApplicationClientId;
}
catch (Exception e)
{
throw SQL.CannotFetchApplicationClientId(configSection.ApplicationClientId, e);
}

_sqlAuthLogger.LogInfo(_typeName, methodName, "Received user-defined Application Client Id");
}
else
{
_sqlAuthLogger.LogInfo(_typeName, methodName, "No user-defined Application Client Id found.");
}

// Create user-defined auth initializer, if any.
if (!string.IsNullOrEmpty(configSection.InitializerType))
{
Expand Down Expand Up @@ -159,13 +177,19 @@ internal class SqlAuthenticationProviderConfigurationSection : ConfigurationSect
/// User-defined auth providers.
/// </summary>
[ConfigurationProperty("providers")]
public ProviderSettingsCollection Providers => (ProviderSettingsCollection)base["providers"];
public ProviderSettingsCollection Providers => (ProviderSettingsCollection)this["providers"];

/// <summary>
/// User-defined initializer.
/// </summary>
[ConfigurationProperty("initializerType")]
public string InitializerType => base["initializerType"] as string;
public string InitializerType => this["initializerType"] as string;

/// <summary>
/// Application Client Id
/// </summary>
[ConfigurationProperty("applicationClientId", IsRequired = false)]
public string ApplicationClientId => this["applicationClientId"] as string;
}

/// <summary>
Expand Down
Expand Up @@ -24,6 +24,7 @@ internal partial class SqlAuthenticationProviderManager
private readonly IReadOnlyCollection<SqlAuthenticationMethod> _authenticationsWithAppSpecifiedProvider;
private readonly ConcurrentDictionary<SqlAuthenticationMethod, SqlAuthenticationProvider> _providers;
private readonly SqlClientLogger _sqlAuthLogger = new SqlClientLogger();
private readonly string _applicationClientId = ActiveDirectoryAuthentication.AdoClientId;

public static readonly SqlAuthenticationProviderManager Instance;

Expand Down
Expand Up @@ -432,6 +432,11 @@ internal static Exception CannotCreateSqlAuthInitializer(string type, Exception
{
return ADP.Argument(System.StringsHelper.GetString(Strings.SQL_CannotCreateAuthInitializer, type), e);
}

static internal Exception CannotFetchApplicationClientId(string type, Exception e)
{
return ADP.Argument(StringsHelper.GetString(Strings.SQL_CannotFetchApplicationClientId, type), e);
}

internal static Exception CannotInitializeAuthProvider(string type, Exception e)
{
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -1905,4 +1905,7 @@
<data name="SQL_SettingDeviceFlowWithCredential" xml:space="preserve">
<value>Cannot use 'Authentication=Active Directory Device Code Flow', if the Credential property has been set.</value>
</data>
</root>
<data name="SQL_CannotFetchApplicationClientId" xml:space="preserve">
<value>Failed to fetch application client id with type '{0}'.</value>
</data>
</root>
Expand Up @@ -41,7 +41,9 @@ public sealed class ActiveDirectoryAuthenticationProvider : SqlAuthenticationPro
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/ctor/*'/>
public ActiveDirectoryAuthenticationProvider() { }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/ctor2/*'/>
public ActiveDirectoryAuthenticationProvider(System.Func<Microsoft.Identity.Client.DeviceCodeResult, System.Threading.Tasks.Task> deviceCodeFlowCallbackMethod) { }
public ActiveDirectoryAuthenticationProvider(string applicationClientId) { }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/ctor3/*'/>
public ActiveDirectoryAuthenticationProvider(System.Func<Microsoft.Identity.Client.DeviceCodeResult, System.Threading.Tasks.Task> deviceCodeFlowCallbackMethod, string applicationClientId = null) { }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/AcquireTokenAsync/*'/>
public override System.Threading.Tasks.Task<SqlAuthenticationToken> AcquireTokenAsync(SqlAuthenticationParameters parameters) { throw null; }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/SetDeviceCodeFlowCallback/*'/>
Expand Down
Expand Up @@ -23,7 +23,6 @@ internal class SqlAuthenticationProviderManager

static SqlAuthenticationProviderManager()
{
var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider();
SqlAuthenticationProviderConfigurationSection configurationSection = null;
try
{
Expand All @@ -41,6 +40,8 @@ static SqlAuthenticationProviderManager()
SqlClientEventSource.Log.TryTraceEvent("Unable to load custom SqlAuthenticationProviders or SqlClientAuthenticationProviders. ConfigurationManager failed to load due to configuration errors: {0}", e);
}
Instance = new SqlAuthenticationProviderManager(configurationSection);

var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider(Instance._applicationClientId);
Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryIntegrated, activeDirectoryAuthProvider);
Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, activeDirectoryAuthProvider);
Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, activeDirectoryAuthProvider);
Expand All @@ -54,6 +55,7 @@ static SqlAuthenticationProviderManager()
private readonly IReadOnlyCollection<SqlAuthenticationMethod> _authenticationsWithAppSpecifiedProvider;
private readonly ConcurrentDictionary<SqlAuthenticationMethod, SqlAuthenticationProvider> _providers;
private readonly SqlClientLogger _sqlAuthLogger = new SqlClientLogger();
private readonly string _applicationClientId = ActiveDirectoryAuthentication.AdoClientId;

/// <summary>
/// Constructor.
Expand All @@ -72,8 +74,25 @@ public SqlAuthenticationProviderManager(SqlAuthenticationProviderConfigurationSe
return;
}

if (!string.IsNullOrEmpty(configSection.ApplicationClientId))
{
try
{
_applicationClientId = configSection.ApplicationClientId;
}
catch (Exception e)
{
throw SQL.CannotFetchApplicationClientId(configSection.ApplicationClientId, e);
}

_sqlAuthLogger.LogInfo(_typeName, methodName, "Received user-defined Application Client Id");
}
else
{
_sqlAuthLogger.LogInfo(_typeName, methodName, "No user-defined Application Client Id found.");
}

// Create user-defined auth initializer, if any.
//
if (!string.IsNullOrEmpty(configSection.InitializerType))
{
try
Expand Down Expand Up @@ -226,13 +245,19 @@ internal class SqlAuthenticationProviderConfigurationSection : ConfigurationSect
/// User-defined auth providers.
/// </summary>
[ConfigurationProperty("providers")]
public ProviderSettingsCollection Providers => (ProviderSettingsCollection)base["providers"];
public ProviderSettingsCollection Providers => (ProviderSettingsCollection)this["providers"];

/// <summary>
/// User-defined initializer.
/// </summary>
[ConfigurationProperty("initializerType")]
public string InitializerType => base["initializerType"] as string;
public string InitializerType => this["initializerType"] as string;

/// <summary>
/// Application Client Id
/// </summary>
[ConfigurationProperty("applicationClientId", IsRequired = false)]
public string ApplicationClientId => this["applicationClientId"] as string;
}

/// <summary>
Expand Down
Expand Up @@ -462,6 +462,11 @@ static internal Exception CannotCreateSqlAuthInitializer(string type, Exception
return ADP.Argument(StringsHelper.GetString(Strings.SQL_CannotCreateAuthInitializer, type), e);
}

static internal Exception CannotFetchApplicationClientId(string type, Exception e)
{
return ADP.Argument(StringsHelper.GetString(Strings.SQL_CannotFetchApplicationClientId, type), e);
}

static internal Exception CannotInitializeAuthProvider(string type, Exception e)
{
return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_CannotInitializeAuthProvider, type), e);
Expand Down Expand Up @@ -772,7 +777,7 @@ static internal Exception UDTUnexpectedResult(string exceptionText)
static internal Exception CannotCompleteDelegatedTransactionWithOpenResults(SqlInternalConnectionTds internalConnection, bool marsOn)
{
SqlErrorCollection errors = new SqlErrorCollection();
errors.Add(new SqlError(TdsEnums.TIMEOUT_EXPIRED, (byte)0x00, TdsEnums.MIN_ERROR_CLASS, null, (StringsHelper.GetString(Strings.ADP_OpenReaderExists, marsOn? ADP.Command : ADP.Connection)), "", 0, TdsEnums.SNI_WAIT_TIMEOUT));
errors.Add(new SqlError(TdsEnums.TIMEOUT_EXPIRED, (byte)0x00, TdsEnums.MIN_ERROR_CLASS, null, (StringsHelper.GetString(Strings.ADP_OpenReaderExists, marsOn ? ADP.Command : ADP.Connection)), "", 0, TdsEnums.SNI_WAIT_TIMEOUT));
return SqlException.CreateException(errors, null, internalConnection);
}
static internal SysTx.TransactionPromotionException PromotionFailed(Exception inner)
Expand Down Expand Up @@ -858,7 +863,7 @@ static internal Exception UDTInvalidSqlType(string typeName)
{
return ADP.Argument(StringsHelper.GetString(Strings.SQLUDT_InvalidSqlType, typeName));
}

static internal Exception UDTInvalidSize(int maxSize, int maxSupportedSize)
{
throw ADP.ArgumentOutOfRange(StringsHelper.GetString(Strings.SQLUDT_InvalidSize, maxSize, maxSupportedSize));
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -4575,4 +4575,7 @@
<data name="SQL_SettingDeviceFlowWithCredential" xml:space="preserve">
<value>Cannot use 'Authentication=Active Directory Device Code Flow', if the Credential property has been set.</value>
</data>
</root>
<data name="SQL_CannotFetchApplicationClientId" xml:space="preserve">
<value>Failed to fetch application client id with type '{0}'.</value>
</data>
</root>
Expand Up @@ -20,13 +20,21 @@ public sealed class ActiveDirectoryAuthenticationProvider : SqlAuthenticationPro
private readonly SqlClientLogger _logger = new SqlClientLogger();
private Func<DeviceCodeResult, Task> _deviceCodeFlowCallback;
private ICustomWebUi _customWebUI = null;
private readonly string _applicationClientId = ActiveDirectoryAuthentication.AdoClientId;

/// <include file='../../../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/ctor/*'/>
public ActiveDirectoryAuthenticationProvider() => new ActiveDirectoryAuthenticationProvider(DefaultDeviceFlowCallback);

/// <include file='../../../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/ctor2/*'/>
public ActiveDirectoryAuthenticationProvider(Func<DeviceCodeResult, Task> deviceCodeFlowCallbackMethod)
public ActiveDirectoryAuthenticationProvider(string applicationClientId) => new ActiveDirectoryAuthenticationProvider(DefaultDeviceFlowCallback, applicationClientId);

/// <include file='../../../../../../doc/snippets/Microsoft.Data.SqlClient/ActiveDirectoryAuthenticationProvider.xml' path='docs/members[@name="ActiveDirectoryAuthenticationProvider"]/ctor3/*'/>
public ActiveDirectoryAuthenticationProvider(Func<DeviceCodeResult, Task> deviceCodeFlowCallbackMethod, string applicationClientId = null)
{
if (applicationClientId != null)
{
_applicationClientId = applicationClientId;
}
SetDeviceCodeFlowCallback(deviceCodeFlowCallbackMethod);
}

Expand Down Expand Up @@ -112,7 +120,7 @@ public override void BeforeUnload(SqlAuthenticationMethod authentication)
#if netstandard
if (parentActivityOrWindowFunc != null)
{
app = PublicClientApplicationBuilder.Create(ActiveDirectoryAuthentication.AdoClientId)
app = PublicClientApplicationBuilder.Create(_applicationClientId)
.WithAuthority(parameters.Authority)
.WithClientName(Common.DbConnectionStringDefaults.ApplicationName)
.WithClientVersion(Common.ADP.GetAssemblyVersion().ToString())
Expand All @@ -124,7 +132,7 @@ public override void BeforeUnload(SqlAuthenticationMethod authentication)
#if netfx
if (_iWin32WindowFunc != null)
{
app = PublicClientApplicationBuilder.Create(ActiveDirectoryAuthentication.AdoClientId)
app = PublicClientApplicationBuilder.Create(_applicationClientId)
.WithAuthority(parameters.Authority)
.WithClientName(Common.DbConnectionStringDefaults.ApplicationName)
.WithClientVersion(Common.ADP.GetAssemblyVersion().ToString())
Expand All @@ -137,7 +145,7 @@ public override void BeforeUnload(SqlAuthenticationMethod authentication)
else
#endif
{
app = PublicClientApplicationBuilder.Create(ActiveDirectoryAuthentication.AdoClientId)
app = PublicClientApplicationBuilder.Create(_applicationClientId)
.WithAuthority(parameters.Authority)
.WithClientName(Common.DbConnectionStringDefaults.ApplicationName)
.WithClientVersion(Common.ADP.GetAssemblyVersion().ToString())
Expand Down

0 comments on commit 03a36c4

Please sign in to comment.