question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Getting MSAL to work with Microsoft.Data.SqlClient to create an azure database on sql server

See original GitHub issue

We 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.

image

image

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:closed
  • Created a year ago
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
MichelZcommented, Aug 9, 2022

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)

0reactions
dgxhubbardcommented, Aug 9, 2022

@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?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Getting MSAL to work with Microsoft.Data.SqlClient ...
Data.SqlClient to create an azure database on sql server #1697 ... MSAL get access token seems to work it has the user I...
Read more >
Connect to Azure SQL with Azure AD authentication and ...
Describes how to use supported Azure Active Directory authentication modes to connect to Azure SQL data sources with SqlClient.
Read more >
Configure and manage Azure AD authentication ...
This article shows you how to create and populate an Azure Active Directory (Azure AD) instance, and then use Azure AD with Azure...
Read more >
Create Azure AD users using service principals
This tutorial walks you through creating an Azure AD user with an Azure AD applications (service principals) in Azure SQL Database.
Read more >
Connect to Azure SQL Database with Azure AD Multi- ...
Data.SqlClient to connect to Azure SQL data sources. In a client C# program, the enum value directs the system to use the Azure...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found