【问题标题】:Xamarin MSAL When to call AcquireTokenSilentXamarin MSAL 何时调用 AcquireTokenSilent
【发布时间】:2019-12-16 20:06:01
【问题描述】:

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

我尝试在每次 API 调用之前调用它,但速度很慢,而且看起来每次都在获取新令牌。它可能需要 200 到 800 毫秒。我还为HttpClient 创建了一个DelegatingHandler,它会查找401 响应并调用AcquireTokenSilent 来刷新令牌。问题是当我从DelegatingHandler 中拨打此电话时应用程序挂起。调用永远不会返回。

【问题讨论】:

    标签: xamarin.forms azure-ad-b2c msal


    【解决方案1】:

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

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

    【讨论】:

    • 嗯,Silent 真的不应该每次都获得一个新的令牌,只要它的缓存有效……听起来像是 MSAL 缓存的问题?
    • @juunas 是的,它每次都返回新的令牌。我只是通过连续调用 4 次来测试它。
    • 你解决过这个问题吗?此外,您是否知道是否有任何方法可以模仿 AWS Amplify 的(看似)行为,该行为似乎集成在应用程序中(例如 ReactJS 本机),它不会重定向您,但在内部似乎执行 MFA 工作,而使用 MSAL它总是浏览器流动吗?这只是 MSAL 和 AWS 的 API 之间的限制/差异吗?
    【解决方案2】:

    即使您发现了问题所在,我还是想确保您遵循正确的模式。

    以下代码来自此链接(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 的每个请求中执行,并向请求标头添加一个令牌。如果令牌快过期了,则此AcquireTokenSilent 方法将首先使用Refresh token 获取一个新令牌,然后将其返回给此方法。

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

    不要自己存储令牌,微软库就是为此而设计的,并以安全的方式存储它们。

    【讨论】:

    • 每次我调用AcquireTokensSilent 它都会刷新令牌,即使它们不需要。如果我的方法不是推荐的方法,那么由于这个错误,我将不得不使用它。
    猜你喜欢
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 2021-11-15
    • 2020-10-16
    • 1970-01-01
    • 1970-01-01
    • 2018-01-24
    • 1970-01-01
    相关资源
    最近更新 更多