Skip to content

Commit

Permalink
Adding a few more AAD changes
Browse files Browse the repository at this point in the history
  • Loading branch information
David-Engel committed Jun 1, 2020
1 parent aa567ff commit b15032c
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ internal static string ConvertToString(object value)

internal static bool TryConvertToAuthenticationType(string value, out SqlAuthenticationMethod result)
{
Debug.Assert(Enum.GetNames(typeof(SqlAuthenticationMethod)).Length == 5, "SqlAuthenticationMethod enum has changed, update needed");
Debug.Assert(Enum.GetNames(typeof(SqlAuthenticationMethod)).Length == 6, "SqlAuthenticationMethod enum has changed, update needed");

bool isSuccess = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2242,7 +2242,7 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo)
}
break;
default:
throw new InvalidOperationException($"Failed to get a token with unsupported auth method {ConnectionOptions.Authentication}.");
throw SQL.UnsupportedAuthenticationSpecified(ConnectionOptions.Authentication);
}

Debug.Assert(fedAuthToken.accessToken != null, "AccessToken should not be null.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,11 @@ internal static Exception UnsupportedSqlAuthenticationMethod(SqlAuthenticationMe
return ADP.NotSupported(System.SRHelper.GetString(SR.SQL_UnsupportedSqlAuthenticationMethod, authentication));
}

internal static Exception UnsupportedAuthenticationSpecified(SqlAuthenticationMethod authentication)
{
return ADP.InvalidOperation(System.SRHelper.GetString(SR.SQL_UnsupportedAuthenticationSpecified, authentication));
}

internal static Exception CannotCreateAuthProvider(string authentication, string type, Exception e)
{
return ADP.Argument(System.SRHelper.GetString(SR.SQL_CannotCreateAuthProvider, authentication, type), e);
Expand Down Expand Up @@ -425,6 +430,12 @@ internal static Exception ParameterCannotBeEmpty(string paramName)
return ADP.ArgumentNull(System.SRHelper.GetString(SR.SQL_ParameterCannotBeEmpty, paramName));
}

internal static Exception ActiveDirectoryInteractiveTimeout()
{
return ADP.TimeoutException(SR.SQL_Timeout_Active_Directory_Interactive_Authentication);
}


//
// SQL.DataCommand
//
Expand Down
18 changes: 18 additions & 0 deletions src/Microsoft.Data.SqlClient/netcore/src/Resources/SR.Designer.cs

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

8 changes: 7 additions & 1 deletion src/Microsoft.Data.SqlClient/netcore/src/Resources/SR.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1869,4 +1869,10 @@
<data name="SQL_SettingIntegratedWithCredential" xml:space="preserve">
<value>Cannot use 'Authentication=Active Directory Integrated', if the Credential property has been set.</value>
</data>
</root>
<data name="SQL_UnsupportedAuthenticationSpecified" xml:space="preserve">
<value>Unsupported authentication specified in this context: {0}</value>
</data>
<data name="SQL_Timeout_Active_Directory_Interactive_Authentication" xml:space="preserve">
<value>Active Directory Interactive authentication timed out. The user took too long to respond to the authentication request.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ internal static ApplicationIntent ConvertToApplicationIntent(string keyword, obj

internal static bool TryConvertToAuthenticationType(string value, out SqlAuthenticationMethod result)
{
Debug.Assert(Enum.GetNames(typeof(SqlAuthenticationMethod)).Length == 5, "SqlAuthenticationMethod enum has changed, update needed");
Debug.Assert(Enum.GetNames(typeof(SqlAuthenticationMethod)).Length == 6, "SqlAuthenticationMethod enum has changed, update needed");

bool isSuccess = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2723,7 +2723,7 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo)
}
break;
default:
throw new InvalidOperationException($"Failed to get a token with unsupported auth method {ConnectionOptions.Authentication}.");
throw SQL.UnsupportedAuthenticationSpecified(ConnectionOptions.Authentication);
}

Debug.Assert(fedAuthToken.accessToken != null, "AccessToken should not be null.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,11 @@ static internal Exception UnsupportedSqlAuthenticationMethod(SqlAuthenticationMe
return ADP.NotSupported(StringsHelper.GetString(Strings.SQL_UnsupportedSqlAuthenticationMethod, authentication));
}

static internal Exception UnsupportedAuthenticationSpecified(SqlAuthenticationMethod authentication)
{
return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_UnsupportedAuthenticationSpecified, authentication));
}

static internal Exception CannotCreateAuthProvider(string authentication, string type, Exception e)
{
return ADP.Argument(StringsHelper.GetString(Strings.SQL_CannotCreateAuthProvider, authentication, type), e);
Expand Down Expand Up @@ -456,6 +461,11 @@ static internal Exception ParameterCannotBeEmpty(string paramName)
return ADP.ArgumentNull(StringsHelper.GetString(Strings.SQL_ParameterCannotBeEmpty, paramName));
}

static internal Exception ActiveDirectoryInteractiveTimeout()
{
return ADP.TimeoutException(Strings.SQL_Timeout_Active_Directory_Interactive_Authentication);
}

//
// SQL.DataCommand
//
Expand Down

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

6 changes: 6 additions & 0 deletions src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -4530,4 +4530,10 @@
<data name="SQLUDT_InvalidSize" xml:space="preserve">
<value>UDT size must be less than {1}, size: {0}</value>
</data>
<data name="SQL_UnsupportedAuthenticationSpecified" xml:space="preserve">
<value>Unsupported authentication specified in this context: {0}</value>
</data>
<data name="SQL_Timeout_Active_Directory_Interactive_Authentication" xml:space="preserve">
<value>Active Directory Interactive authentication timed out. The user took too long to respond to the authentication request.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics;
using System.Linq;
using System.Security;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Identity.Client;

Expand Down Expand Up @@ -44,6 +48,7 @@ public override Task<SqlAuthenticationToken> AcquireTokenAsync(SqlAuthentication
.WithAuthority(parameters.Authority)
.WithClientName(Common.DbConnectionStringDefaults.ApplicationName)
.WithClientVersion(Common.ADP.GetAssemblyVersion().ToString())
.WithRedirectUri("http://localhost")
.Build();

if (parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryIntegrated)
Expand All @@ -62,17 +67,89 @@ public override Task<SqlAuthenticationToken> AcquireTokenAsync(SqlAuthentication
.WithCorrelationId(parameters.ConnectionId)
.ExecuteAsync().Result;
}
else if (parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryInteractive)
{
var accounts = await app.GetAccountsAsync();
IAccount account;
if (!string.IsNullOrEmpty(parameters.UserId))
{
account = accounts.FirstOrDefault(a => parameters.UserId.Equals(a.Username, System.StringComparison.InvariantCultureIgnoreCase));
}
else
{
account = accounts.FirstOrDefault();
}

if (null != account)
{
try
{
result = await app.AcquireTokenSilent(scopes, account).ExecuteAsync();
}
catch (MsalUiRequiredException)
{
result = await AcquireTokenInteractive(app, scopes, parameters.ConnectionId, parameters.UserId);
}
}
else
{
result = await AcquireTokenInteractive(app, scopes, parameters.ConnectionId, parameters.UserId);
}
}
else
{
result = await app.AcquireTokenInteractive(scopes)
.WithCorrelationId(parameters.ConnectionId)
.WithLoginHint(parameters.UserId)
.ExecuteAsync();
throw SQL.UnsupportedAuthenticationSpecified(parameters.AuthenticationMethod);
}

return new SqlAuthenticationToken(result.AccessToken, result.ExpiresOn);
});

private async Task<AuthenticationResult> AcquireTokenInteractive(IPublicClientApplication app, string[] scopes, Guid connectionId, string userId)
{
CancellationTokenSource cts = new CancellationTokenSource();
#if netcoreapp
/*
* On .NET Core, MSAL will start the system browser as a separate process. MSAL does not have control over this browser,
* but once the user finishes authentication, the web page is redirected in such a way that MSAL can intercept the Uri.
* MSAL cannot detect if the user navigates away or simply closes the browser. Apps using this technique are encouraged
* to define a timeout (via CancellationToken). We recommend a timeout of at least a few minutes, to take into account
* cases where the user is prompted to change password or perform 2FA.
*
* https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/System-Browser-on-.Net-Core#system-browser-experience
*/
cts.CancelAfter(180000);
#endif
try
{
return await app.AcquireTokenInteractive(scopes)
/*
* We will use the MSAL Embedded or System web browser which changes by Default in MSAL according to this table:
*
* Framework Embedded System Default
* -------------------------------------------
* .NET Classic Yes Yes^ Embedded
* .NET Core No Yes^ System
* .NET Standard No No NONE
* UWP Yes No Embedded
* Xamarin.Android Yes Yes System
* Xamarin.iOS Yes Yes System
* Xamarin.Mac Yes No Embedded
*
* ^ Requires "http://localhost" redirect URI
*
* 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);
}
catch (OperationCanceledException)
{
throw SQL.ActiveDirectoryInteractiveTimeout();
}
}

/// <summary>
/// Checks support for authentication type in lower case.
/// Interactive authentication added.
Expand Down

0 comments on commit b15032c

Please sign in to comment.