xamarin 处理多个AcquireTokenInteractive调用并阻止多个浏览器登录请求(MSAL)

nqwrtyyt  于 2022-12-25  发布在  其他
关注(0)|答案(1)|浏览(164)

我们有许多调用都需要来自MSAL的令牌。这些调用并行发生,如下所示。

AuthenticationResult result = await this.pca.AcquireTokenSilent(scopes, account).ExecuteAsync();

headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);

我们正在处理所有必要的MSAL异常,例如MsalUiRequiredException --为了缩短问题,我刚刚删除了这些部分。
在RefreshToken过期的情况下,我们面临着多个并行调用导致抛出多个MsalUiRequiredExceptions,从而导致代码多次调用AcquireTokenInteractive
这意味着用户最终要处理一堆浏览器登录信息。其他人如何处理多个不相关的调用,这些调用需要交互式登录,因此会抛出一个浏览器?

tcomlyy6

tcomlyy61#

我们现在使用SemaphoreSlim来控制对试图获取令牌的代码的访问。
在这个问题的评论线程中进行了一些讨论之后,我确实考虑过使用lock语句,但在 Package 异步调用时,这并不被认为是一个好主意,这是因为潜在的死锁和不同线程在等待返回时试图释放它们没有访问权限的锁的可能性。
代码现在如下所示

await this.semaphoreSlim.WaitAsync();

try
{
    var account = await this.GetCurrentAccount();
    AuthenticationResult result = await this.pca.AcquireTokenSilent(scopes, account).ExecuteAsync();
    return new AuthenticationResultWrapper(result);
}
catch (MsalUiRequiredException)
{
    try
    {
        // Acquire token interactively
        AuthenticationResult authResult = await this.pca.AcquireTokenInteractive(scopes)
                                                        .WithParentActivityOrWindow(this.uiParent)
                                                        .ExecuteAsync();

        return new AuthenticationResultWrapper(authResult);
    }
    catch (MsalServiceException client) when (client.Message.Contains(BreathRmCloudDataSyncService.MsalForgottenPasswordErrorMessageCode))
    {
        // User selected forgotten password flow
        IAuthenticationResult authResult = await this.HandleClinicalServiceHandleForgottenPasswordAsync();
        return authResult;
    }
    catch (MsalException msalException) when (BreathRmCloudDataSyncService.ExceptionIsMsalCancellation(msalException))
    {
        // Nothing to do here, user cancelled the flow
        this.logger.LogInteraction("User cancelled authentication during interactive token acquirement.");
        throw;
    }
    catch (Exception exc)
    {
        this.logger.LogException(exc, "AcquireTokenInternalAsync Try Interactively Failed: Unknown Exception: " + exc.Message);
        return null;
    }
}
catch (Exception e)
{
    this.logger.LogException(e, "ClinicalService - AcquireTokenAsync");
    throw;
}
finally
{
    this.semaphoreSlim.Release();
}

相关问题