Xamarin MSAL 何时调用 AcquireTokenSilent

Xamarin MSAL When to call AcquireTokenSilent

MSAL 示例展示了如何登录、获取访问令牌以及使用该令牌调用 API。它没有显示的是如何调用第 2、第 3 等 API 调用。您是否应该缓存您的访问令牌并将其用于每个 API 调用直到它过期或在进行每个 API 调用之前调用 AquireTokenSilent? MSAL 没有 return 刷新令牌,所以我无法自己刷新它。我将访问令牌配置为在一小时后过期。如果用户使用该应用程序超过一个小时,我认为我需要刷新令牌。

我尝试在每次 API 调用之前调用它,但它很慢,而且看起来每次都获得一个新令牌。它可能需要 200 到 800 毫秒的任何时间。我还为 HttpClient 创建了一个 DelegatingHandler,它查找 401 响应并调用 AcquireTokenSilent 来刷新令牌。问题是当我从 DelegatingHandler 中进行此调用时应用程序挂起。调用从不 returns.

编辑:我为此在 Github 中提交了一个错误,因为 MSAL 应该 return 缓存的令牌,而不是每次都刷新令牌。这没有发生,因为我使用的是 user_impersonate 范围。 Microsoft 对此进行了错误修复。同时,如果您遇到此问题并且错误修复尚未发布,请删除 user_impersonate 范围,它应该可以正常工作。我已经删除了我自己用来缓存令牌的代码。

原文: 我解决了这个问题。我相信正确的路径是缓存令牌并将其用于后续调用。使用 DelegatingHandler 观察 401 响应,然后调用 AcquireTokenSilent 即可。我有一个导致应用程序挂起的错误。这似乎是个好方法。

即使您已经弄清楚问题出在哪里,我还是想确保您遵循的是正确的模式。

以下代码来自此link (link):

private async Task InitializeGraphClientAsync()
{
    var currentAccounts = await PCA.GetAccountsAsync();
    try
    {
        if (currentAccounts.Count() > 0)
        {
            // Initialize Graph client
            GraphClient = new GraphServiceClient(new DelegateAuthenticationProvider(
                async (requestMessage) =>
                {
                    var result = await PCA.AcquireTokenSilent(Scopes, currentAccounts.FirstOrDefault())
                        .ExecuteAsync();

                    requestMessage.Headers.Authorization =
                        new AuthenticationHeaderValue("Bearer", result.AccessToken);
                }));

            await GetUserInfo();

            IsSignedIn = true;
        }
        else
        {
            IsSignedIn = false;
        }
    }
    catch(Exception ex)
    {
        Debug.WriteLine(
            $"Failed to initialized graph client. Accounts in the msal cache: {currentAccounts.Count()}. See exception message for details: {ex.Message}");
    }
}

重要的部分是他们创建新的 Graph 客户端时。他们向 aqcuire 添加了一个将随每个请求一起执行的委托,并向请求添加了一个令牌 header。如果令牌即将过期,那么此 AcquireTokenSilent 方法将首先使用 Refresh token 获取新令牌,然后将其返回给此方法。

如果您使用自己的 API 并且还需要此令牌,您可以使用相同的逻辑创建自己的委托。对于每个请求,您执行 method/delegate 将(缓存的或新的)令牌添加到您的请求中。

不要自己存储令牌,Microsoft 库就是为此而创建的,并以安全的方式存储它们。