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 dca5f8f
Show file tree
Hide file tree
Showing 15 changed files with 161 additions and 20 deletions.
26 changes: 26 additions & 0 deletions doc/samples/ApplicationClientIdAzureAuthenticationProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//<Snippet1>
using System;
using Microsoft.Data.SqlClient;

namespace CustomAuthenticationProviderExamples
{
public class Program
{
public static void Main()
{
// Supported for all authentication modes supported by ActiveDirectoryAuthenticationProvider
ActiveDirectoryAuthenticationProvider provider = new ActiveDirectoryAuthenticationProvider("<application_client_id>");
if (provider.IsSupported(SqlAuthenticationMethod.ActiveDirectoryInteractive))
{
SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, provider);
}

using (SqlConnection sqlConnection = new SqlConnection("Server=<myserver>.database.windows.net;Authentication=Active Directory Interactive;Database=<db>;"))
{
sqlConnection.Open();
Console.WriteLine("Connected successfully!");
}
}
}
}
//</Snippet1>
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,30 @@
</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>
<remarks>
<format type="text/markdown">
<![CDATA[
## Examples
The following example demonstrates providing user-defined application client id to SqlClient for performing "Active Directory Interactive" authentication method:
[!code-csharp[ActiveDirectory_ApplicationClientId Example#1](~/../sqlclient/doc/samples/ApplicationClientIdAzureAuthenticationProvider.cs#1)]
]]>
</format>
</remarks>
</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
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ public sealed partial class ActiveDirectoryAuthenticationProvider : SqlAuthentic
/// <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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ internal partial class SqlAuthenticationProviderManager
{
static SqlAuthenticationProviderManager()
{
var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider();
Instance = new SqlAuthenticationProviderManager();
var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider(Instance._applicationClientId);
Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, activeDirectoryAuthProvider);
Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryIntegrated, activeDirectoryAuthProvider);
Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, activeDirectoryAuthProvider);
Expand Down
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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.

Original file line number Diff line number Diff line change
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>
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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.

Original file line number Diff line number Diff line change
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>
Loading

0 comments on commit dca5f8f

Please sign in to comment.