Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to get ServiceClientCredentials after migrating from ADAL to MSAL

The support for ADAL ends on June 30, 2022 and Microsoft recommends migrating applications to MSAL.

During migration, I encountered a difficulty migrating a code that accesses Data Lake Storage from ADAL to MSAL. My almost-working attempt is:

// Before migration (authenticate using obsolete ADAL)
ClientCredential clientCredential = new ClientCredential(clientId, clientSecret);
ServiceClientCredentials credentials = await ApplicationTokenProvider.LoginSilentAsync(tenantId, clientCredential);

var adlsClient = AdlsClient.CreateClient(dataLakeStoreName, serviceCredentials)
// After migration (authenticate using newer MSAL)
var clientApplication = ConfidentialClientApplicationBuilder
        .Create(clientId)
        .WithClientSecret(clientSecrret)
        .WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"))
        .Build();
AuthenticationResult credentials = await (new[] { $"https://datalake.azure.net/.default" })
        .ExecuteAsync();

// We no longer have ServiceClientCredentials object, so the only overload left is the one that accepts a bearer token as a string:
var adlsClient = AdlsClient
        .CreateClient(dataLakeStoreName, $"{credentials.TokenType} {credentials.AccessToken}");

The above MSAL code works for a while, but with ServiceClientCredentials gone, we lost the object responsible for refreshing a token. So, when the token expires, adlsClient now stops working.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Is there any simple way to create a ServiceClientCredentials with MSAL?
Or do we need to code the logic that refreshes the token ourselves when we migrate to MSAL?

>Solution :

Got same problem lately. You can implement your own ServiceClientCredentials that can utilize IConfidentialClientApplication to manage access token. For example:

public class DataLakeGen1ClientCredentials : ServiceClientCredentials
    {
        private readonly IConfidentialClientApplication _application;

        public DataLakeGen1ClientCredentials(string? appId, string? secretKey, string? directoryId)
        {
            _application = ConfidentialClientApplicationBuilder
                .Create(appId)
                .WithClientSecret(secretKey)
                .WithAuthority(new Uri($"https://login.microsoftonline.com/{directoryId}"))
                .Build();
        }

        public override async Task ProcessHttpRequestAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
        {
            HttpRequestHeaders httpRequestHeaders = request.Headers;
            var authResult = await _application.AcquireTokenForClient(new[] { $"https://datalake.azure.net/.default" })
                .ExecuteAsync(cancellationToken).ConfigureAwait(false);
            httpRequestHeaders.Authorization = new AuthenticationHeaderValue(authResult.TokenType, authResult.AccessToken);

            await base.ProcessHttpRequestAsync(request, cancellationToken).ConfigureAwait(false);
        }
    }

Than you can use it to init your adlsClient:

var serviceCredentials = new DataLakeGen1ClientCredentials(clientId, clientSecret, tenantId);
AdlsClient client = AdlsClient.CreateClient(DataLakeStoreName, serviceCredentials);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading