从 ADAL 迁移到 MSAL 后如何获取 ServiceClientCredentials

发布于 2025-01-10 02:04:06 字数 1605 浏览 2 评论 0原文

对 ADAL 的支持将于 2022 年 6 月 30 日结束,Microsoft 建议将应用程序迁移到 MSAL

在迁移过程中,我在将访问 Data Lake Storage 的代码从 ADAL 迁移到 MSAL 时遇到了困难。我几乎可以工作的尝试是:

// 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}");

上面的 MSAL 代码工作了一段时间,但是随着 ServiceClientCredentials 消失,我们丢失了负责刷新令牌的对象。因此,当令牌过期时,adlsClient 现在将停止工作。

是否有任何简单的方法可以使用 MSAL 创建 ServiceClientCredentials? 或者当我们迁移到 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(
quot;https://login.microsoftonline.com/{tenantId}"))
        .Build();
AuthenticationResult credentials = await (new[] { 
quot;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, 
quot;{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.

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

短叹 2025-01-17 02:04:06

最近遇到同样的问题。您可以实现自己的 ServiceClientCredentials,它可以利用 IConfidentialClientApplication 来管理访问令牌。例如:

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);
        }
    }

您需要重写 AdlsClient 使用的 ProcessHttpRequestAsync,以便在发送请求之前将令牌插入到 HTTP 标头中。 AcquireTokenForClient 将为您提供有效的令牌。

使用 ServiceClientCredentials 的此实现,您可以初始化 adlsClient 并像以前一样使用它:

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

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(
quot;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[] { 
quot;https://datalake.azure.net/.default" })
                .ExecuteAsync(cancellationToken).ConfigureAwait(false);
            httpRequestHeaders.Authorization = new AuthenticationHeaderValue(authResult.TokenType, authResult.AccessToken);

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

You need to override ProcessHttpRequestAsync that is used by the AdlsClient to insert token into HTTP headers before sending the request. AcquireTokenForClient will provide you a valid token.

Using this implementation of ServiceClientCredentials you can init your adlsClient and use it as previously:

var serviceCredentials = new DataLakeGen1ClientCredentials(clientId, clientSecret, tenantId);
AdlsClient client = AdlsClient.CreateClient(DataLakeStoreName, serviceCredentials);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文