AcquireTokenSilent 始终无法静默获取令牌

AcquireTokenSilent always Failed to acquire token silently

使用 ADAL 我有两个 AuthenticationContext 使用令牌缓存持久化在 SQL.

使用AcquireTokenByAuthorizationCode它在数据库中写入令牌,但是当使用AcquireTokenSilent时我总是得到

Failed to acquire token silently. Call method AcquireToken

以下是复制问题的详细信息:

我创建一个上下文

AuthenticationContext authContext = new AuthenticationContext(_authority, new AzureAdalCache(companyId, _entries, _unitOfWork));

然后我通过授权获取Token

authContext.AcquireTokenByAuthorizationCode(authorizationCode, new Uri(redirectUri), _clientCredential);

此时,它在数据库中保存了一个条目

然后如果我调用这个我得到一个异常。

authContext.AcquireTokenSilent(_authority, _clientCredential, new UserIdentifier(companyId.ToString(), UserIdentifierType.UniqueId)).AccessToken;

我也试过同样的结果:

authContext.AcquireTokenSilent(_authority, _clientId).AccessToken;
authContext.AcquireTokenSilent(_authority, _clientCredential, UserIdentifier.AnyUser).AccessToken;

我 Post 我的 AzureAdalCachethis Gist 中实现。

缓存的每个条目是like this

我错过了什么?

更新

根据@vibronet 的评论回答我有这个

AuthenticationContext authContext = new AuthenticationContext(_authority, new AzureAdalCache(companyId, _entries, _unitOfWork));
authContext.AcquireTokenByAuthorizationCode(authorizationCode, new Uri(redirectUri), _clientCredential, _eWSResource);
string result = authContext.AcquireTokenSilent(_eWSResource, _clientId, UserIdentifier.AnyUser).AccessToken;

我不明白调用:

authContext.AcquireTokenSilent(
    _authority,
    _clientCredential,
    new UserIdentifier(companyId.ToString(), UserIdentifierType.UniqueId)
).AccessToken;

UserIdentifier 必须与缓存中的值匹配,并且 CompanyID 听起来不像您为令牌取回的任何标识符。

请查看我在另一个线程上向您指出的示例,特别是在 https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet/blob/master/TodoListWebApp/Controllers/TodoListController.cs

中调用 AcquireTokenSilent 时使用的标识符

您无法选择在该调用中使用哪个标识符,这取决于 AAD 发出的声明。您可以选择的唯一标识符是在缓存实例级别,而不是在单个 AcquireToken* 调用中。

问题是基本上我在我的应用程序中使用了 Common Authority https://login.windows.net/common/oauth2/authorize。它适用于 AcquireTokenByAuthorizationCode() 但不适用于 AcquireTokenSilent()。

所以我需要它在调用 AcquireTokenByAuthorizationCode() 时保存 TenantId,并且在调用 AcquireTokenSilent() 时授权使用像 https://login.windows.net/<tenant ID>/oauth2/authorize 这样的授权。这样上面的代码就可以工作了。

我在 ASPNetCore (1.0) 中遇到了同样的问题,原因是我在登录后没有存储身份验证令牌。我通过在启动 class 中添加 OnAuthorizationCodeReceived 解决了这个问题并将我的响应类型更改为 ResponseType = OpenIdConnectResponseType.CodeIdToken.

希望对您有所帮助。

样本: https://github.com/Azure-Samples/active-directory-dotnet-webapp-webapi-openidconnect-aspnetcore/blob/aspnet10/WebApp-WebAPI-OpenIdConnect-DotNet/Startup.cs#L100

检查缓存中是否存在令牌,否则退出并要求用户登录。

AuthenticationContext authContext = new AuthenticationContext(Startup.Authority,
                        new NaiveSessionCache(userObjectID));
                    if (authContext.TokenCache.Count == 0)
                    {
                        authContext.TokenCache.Clear();
                        CosmosInterface.Utils.AuthenticationHelper.token = null;
                        HttpContext.GetOwinContext().Authentication.SignOut(
                            OpenIdConnectAuthenticationDefaults.AuthenticationType,
                            CookieAuthenticationDefaults.AuthenticationType);
                    }

这是一个老问题 - 但对我来说,我需要在客户端清除我的 cookie,然后它会强制浏览器重新授权,然后一切又好了。