Getting MSAL to work with Microsoft.Data.SqlClient to create an azure database on sql server
See original GitHub issueWe have a desktop app our customers purchase, and some customers want to access azure while running azure ad. We use a DbConnectionInterceptor to determine if azure is used and get the access token. This code is put together from the WPF app example. What should the Authentication setting be, for Microsoft.Data.SqlClient connection string, is my first question. Next why does this have an error with the connection string:
Data Source=tcp:foo.database.windows.net,1433;Pooling=True;Authentication=ActiveDirectoryIntegrated
We are not setting a password.
Our code not event make it to our DbConnectionInterceptor.
` public class AzureAdDbConnectorInterceptor : DbConnectionInterceptor { private static string ClientId = “c32c25e9-2f19-4171-ad22-83e969f65e57”;
private static string Tenant = "common";
private static IPublicClientApplication _clientApp;
public static IPublicClientApplication PublicClientApp { get { return _clientApp; } }
static AzureAdDbConnectorInterceptor ()
{
_clientApp = PublicClientApplicationBuilder.Create ( ClientId )
.WithAuthority ( AzureCloudInstance.AzurePublic, Tenant )
.WithDefaultRedirectUri ()
.Build ();
}
public override InterceptionResult ConnectionOpening (
DbConnection connection,
ConnectionEventData eventData,
InterceptionResult result )
{
var sqlConnection = ( SqlConnection ) connection;
if ( DoesConnectionNeedAccessToken ( sqlConnection ) )
{
sqlConnection.AccessToken = GetAuthenticationToken ();
}
return base.ConnectionOpening ( connection, eventData, result );
}
public override async ValueTask<InterceptionResult> ConnectionOpeningAsync (
DbConnection connection,
ConnectionEventData eventData,
InterceptionResult result,
CancellationToken cancellationToken = default )
{
var sqlConnection = ( SqlConnection ) connection;
if ( DoesConnectionNeedAccessToken ( sqlConnection ) )
{
sqlConnection.AccessToken = GetAuthenticationToken ();
}
return await base.ConnectionOpeningAsync ( connection, eventData, result, cancellationToken );
}
private static bool DoesConnectionNeedAccessToken ( SqlConnection connection )
{
var connectionStringBuilder = new SqlConnectionStringBuilder ( connection.ConnectionString );
var dataSource = connectionStringBuilder.DataSource;
var contains = false;
if ( dataSource.Contains ( MsSqlConstants.AzureUrl, StringComparison.OrdinalIgnoreCase ) )
contains = true;
return contains;
//&& string.IsNullOrEmpty ( connectionStringBuilder.UserID );
}
public string ResultText
{ get; set; }
private string GetAuthenticationToken ()
{
AuthenticationResult authResult = null;
var scopes = new List<string> () { "user.read", "user.write" };
var accountResult = _clientApp.GetAccountsAsync ();
accountResult.Wait ();
var firstAccount = accountResult.Result.FirstOrDefault ();
try
{
Task<AuthenticationResult> result = _clientApp.AcquireTokenSilent ( scopes, firstAccount ).ExecuteAsync ();
result.Wait ();
authResult = result.Result;
}
catch ( MsalUiRequiredException ex )
{
// A MsalUiRequiredException happened on AcquireTokenSilent.
// This indicates you need to call AcquireTokenInteractive to acquire a token
System.Diagnostics.Debug.WriteLine ( $"MsalUiRequiredException: {ex.Message}" );
try
{
Task<AuthenticationResult> result =
_clientApp.AcquireTokenInteractive ( scopes ).
WithUseEmbeddedWebView ( true ).
ExecuteAsync ();
result.Wait ();
authResult = result.Result;
}
catch ( MsalException msalex )
{
ResultText = $"Error Acquiring Token:{System.Environment.NewLine}{msalex}";
}
}
catch ( Exception ex )
{
ResultText = $"Error Acquiring Token Silently:{System.Environment.NewLine}{ex}";
}
if ( authResult != null )
return authResult.AccessToken;
else
return null;
}
}
`
Issue Analytics
- State:
- Created a year ago
- Comments:6 (2 by maintainers)
Top GitHub Comments
Try removing
Authentication=ActiveDirectoryIntegrated
from your connection string when you use an access token.e.g. https://github.com/RayGHeld/Azure-SQL-Authentication-With-Access-Tokens/blob/main/Azure_SQL.cs See base connection string: https://github.com/RayGHeld/Azure-SQL-Authentication-With-Access-Tokens/blob/729c3439d39e7f314fa6d7908fadf3ad18a7d690/Azure_SQL.cs#L25
and how it’s used with access token: https://github.com/RayGHeld/Azure-SQL-Authentication-With-Access-Tokens/blob/729c3439d39e7f314fa6d7908fadf3ad18a7d690/Azure_SQL.cs#L112
(Also, this seems to be more of a problem with SqlClient than MSAL)
@jmprieur setting the scope and @MichelZ removing the Authentication setting go me into the db interceptor. In the db interceptor, I try and get a token, in GetAuthenticationToken, but using
` var accountResult = _clientApp.GetAccountsAsync (); accountResult.Wait ();
var firstAccount = accountResult.Result.FirstOrDefault (); `
returns null. How do I get the logged in users azure ad information to get the access token?