.Net Core 3.1 Azure Web App - 无法静默获取令牌,因为在缓存中找不到令牌。调用方法 AcquireToken

.Net Core 3.1 Azure Web App - Failed to acquire token silently as no token was found in the cache. Call method AcquireToken

我有一个 Azure Web 应用程序可以对用户进行身份验证,然后导航到一个页面,在该页面上检索并显示在应用程序中。

大多数时候应用程序运行良好,但 App Insights 偶尔会突出显示 Failed to acquire token silently as no token was found in the cache. Call method AcquireToken。一些用户不时在此页面上报告问题(这是不一致的,因此对于较大的用户群,一天可能会发生几次)。问题是目前错误没有得到处理,我正在尝试弄清楚如何调用 AcquireTokenAsync.

以下是returnstoken(或不)的方法:

private async Task<string> GetUserAccessToken()
{
    try
    {
        // Credentials for app
        // _clientId and _clientSecret represent the app info - not shown here in code
        ClientCredential credential = new ClientCredential(_clientId, _clientSecret);
        
        //Construct token cache
        ITokenCacheFactory cacheFactory = Request.HttpContext.RequestServices.GetRequiredService<ITokenCacheFactory>();
        TokenCache cache = cacheFactory.CreateForUser(Request.HttpContext.User);
        AuthenticationContext authContext = new AuthenticationContext(_authority, cache);
        
        // guid of the user currently logged into the app
        string objectID = _userObjectId;
        UserIdentifier userIdentifier = new UserIdentifier(objectID, UserIdentifierType.UniqueId);

        string resource = "https://test.sharepoint.com";
        
        AuthenticationResult result = await authContext.AcquireTokenSilentAsync(resource, credential, userIdentifier);
                
        return result.AccessToken;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

如果我正确理解流程,此处的 Web 应用程序将代表当前登录的用户使用它自己的凭据请求令牌。(根据声明的方法签名,我理解这一点是否正确 - Identifier of the user token is requested for. This parameter can be Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier.Any.)

现在,当失败时,我需要调用 AcquireTokenAsync。有许多可用的方法,但我似乎找不到能够满足此要求的方法。

在建议出现之前,我无法使用 AcquireTokenAsync(resource, clientId, redirectUri,new PlatformParameters(PromptBehavior.Auto));,因为 PlatformParameters 上的构造函数已更改,需要实现 ICustomWebUi,并且此流程在 PlatformParameters 上不受支持据我所知,.Net Core 3.1 使它无法使用。

AcquireTokenAsync(resource, credentials) 工作并且 returns 一个令牌,但是,当使用该令牌时,我在访问 Sharepoint 资源时得到 401 Unauthorized ,很可能是因为令牌不同并且现在请求代表应用程序而不是用户登录到应用程序(如果我正确地遵循了这个思路......)。

我的问题是 - 我应该调用哪个方法?在调用 AcquireTokenAsync 之前我需要添加什么吗?如果需要,我应该使用 10 个左右的重载中的哪一个?我尝试使用 AcquireTokenAsync(resource, credenetial, userAssertion) 并传入我在 User 登录时检索到的 AccessToken,但后来我得到了 Assertion failed signature validation 或它的变体。如果我理解正确,UserAssertion 可以用 1,2 或 3 个参数初始化,我尝试提供登录应用程序的用户当前的 AccessToken,但没有成功。

非常感谢任何帮助,因为我已经看了两天了。

我花了更多时间对此进行调查,但是 none 可用的方法对我来说是有效的。授权流程不是代表流程,而是 auth-code flow。 link 适用于较新的 MSAL 库,但概念在那里。该应用程序是一个 .net 核心 Web 应用程序,它指示用户登录。当他们登录时,一旦他们成功通过身份验证,授权代码就会传递到响应中。

然后使用授权码调用 AcquireTokenByAuthorizationCodeAsync(AuthCode, Uri, ClientCredential, UserIdentifier)。此 return 是可以存储在分布式令牌缓存中然后用于身份验证以访问给定资源的有效访问令牌。

我最大的问题是错误提示您需要使用 AcquireTokenAsync 来检索新令牌。这在一定程度上是正确的,因为为了调用 14 种左右的方法中的任何一种,您将需要不同的信息位,这取决于您在应用程序中设置身份验证流程的方式。

因为我使用的应用程序使用了授权代码流,所以我需要获得一个新的授权代码。这意味着将用户重定向到登录,如果登录成功,则在响应中捕获授权代码,然后调用适当的 AcquireTokenAsync 方法,该方法将授权代码作为参数以及应用程序信息、uri 等。

为了解决这个问题,我使用了 Acquiring tokens with auth codes in web apps 上 Microsoft Github 页面提供的信息。在这里,我找到了有关如何设置身份验证流程的示例,但最重要的是,如果用户需要重新进行身份验证,如何触发新的身份验证流程。

我包装了会抛出 AdalSilentTokenAcquisitionException 的代码,捕获错误并 return 一个 RedirectToAction

return RedirectToAction("ActionName", "Controller", new RouteValues);

以上将用户重定向到特定控制器中的给定操作,并传递可以包含其他参数的对象。在我的例子中,它是一个 new { redirectUri = redirectUriString},它是一个字符串对象,其中包含用户将尝试导航的 URL。我用一个小方法构造了它,该方法使用当前的 HttpRequest 来查找用户试图到达的 url。

接下来,我设置的响应该重定向的控制器:

[HttpGet("/SignIn")]
public IActionResult SignIn([FromQuery(Name ="redirectUri")]string redirectUri)
{
    return Challenge
        (
            new AuthenticationProperties { RedirectUri = WebUtility.UrlDecode(redirectUri) },
            OpenIdConnectDefaults.AuthenticationScheme
        );
}

这里,Challenge 是 returned。质询会触发对 Startup class 中设置的身份验证流程的调用。我认为这里的整个流程是该方法将派人去检查该启动中的任何内容,就我所处理的应用程序而言,它会提示用户登录、获取授权代码、请求新的访问令牌,一旦收到并保存在分布式令牌缓存中,用户将被重定向到我通过的 redirectUri

我希望这对可能遇到类似问题的任何人有所帮助,或者至少给他们一个起点。