c# - 代码 : TokenNotFound Message: User not found in token cache. 可能服务器已重新启动

标签 c# .net asp.net-mvc asp.net-core azure-active-directory

我有以下功能可以使用 graph api 从 active directory 调用用户。 这个函数在文本框的每个 keyup 上被击中。但是我收到以下错误

Code: TokenNotFound Message: User not found in token cache. Maybe the server was restarted.

在线

var user = await graphClient.Users.Request().GetAsync();

完整功能如下:

     public async Task<string> GetUsersJSONAsync(string textValue)
            {
               // email = email ?? User.Identity.Name ?? User.FindFirst("preferred_username").Value;
                var identifier = User.FindFirst(Startup.ObjectIdentifierType)?.Value;
                var graphClient = _graphSdkHelper.GetAuthenticatedClient(identifier);
                string usersJSON = await GraphService.GetAllUserJson(graphClient, HttpContext, textValue);
                return usersJSON;
            }


    public static async Task<string> GetAllUserJson(GraphServiceClient graphClient, HttpContext httpContext, string textValue)
            {
               // if (email == null) return JsonConvert.SerializeObject(new { Message = "Email address cannot be null." }, Formatting.Indented);

                try
                {
                    // Load user profile.
                    var user = await graphClient.Users.Request().GetAsync();                    
                    return JsonConvert.SerializeObject(user.Where(u => !string.IsNullOrEmpty(u.Surname) && ( u.Surname.ToLower().StartsWith(textValue) || u.Surname.ToUpper().StartsWith(textValue.ToUpper()))), Formatting.Indented);
                }
                catch (ServiceException e)
                {
                    switch (e.Error.Code)
                    {
                        case "Request_ResourceNotFound":
                        case "ResourceNotFound":
                        case "ErrorItemNotFound":
                        //case "itemNotFound":
                        //    return JsonConvert.SerializeObject(new { Message = $"User '{email}' was not found." }, Formatting.Indented);
                        //case "ErrorInvalidUser":
                        //    return JsonConvert.SerializeObject(new { Message = $"The requested user '{email}' is invalid." }, Formatting.Indented);
                        case "AuthenticationFailure":
                            return JsonConvert.SerializeObject(new { e.Error.Message }, Formatting.Indented);
                        case "TokenNotFound":
                            await httpContext.ChallengeAsync();
                            return JsonConvert.SerializeObject(new { e.Error.Message }, Formatting.Indented);
                        default:
                            return JsonConvert.SerializeObject(new { Message = "An unknown error has occured." }, Formatting.Indented);
                    }
                }
            }


 // Gets an access token. First tries to get the access token from the token cache.
        // Using password (secret) to authenticate. Production apps should use a certificate.
        public async Task<string> GetUserAccessTokenAsync(string userId)
        {
            _userTokenCache = new SessionTokenCache(userId, _memoryCache).GetCacheInstance();

            var cca = new ConfidentialClientApplication(
                _appId,
                _redirectUri,
                _credential,
                _userTokenCache,
                null);

            if (!cca.Users.Any()) throw new ServiceException(new Error
            {
                Code = "TokenNotFound",
                Message = "User not found in token cache. Maybe the server was restarted."
            });

            try
            {
                var result = await cca.AcquireTokenSilentAsync(_scopes, cca.Users.First());
                return result.AccessToken;
            }

            // Unable to retrieve the access token silently.
            catch (Exception)
            {
                throw new ServiceException(new Error
                {
                    Code = GraphErrorCode.AuthenticationFailure.ToString(),
                    Message = "Caller needs to authenticate. Unable to retrieve the access token silently."
                });
            }
        }

你能帮我看看哪里出了问题吗?

最佳答案

我知道这已经 4 个月大了 - 这对您来说仍然是个问题吗?

正如之前的受访者所指出的,您看到的错误是在您的代码中用于处理空用户集合的 catch block 中引发的。

万一你卡在这上面,或者其他人来到这里 - 如果你使用了 this sample (或在任何方面使用 ConfidentialClientApplication)并抛出此异常,这是因为您的 _userTokenCache 没有用户*。当然,不是因为你的AD没有用户,否则就无法认证。很可能是因为浏览器中的旧 cookie 作为访问 token 传递给了 authProvider。您可以使用 Fiddler(或只检查您的本地主机浏览器 cookie)来找到它(应该称为 AspNetCore.Cookies,但您可能想要清除所有这些)。

如果您将 token 缓存存储在 session 中(如示例所示),请记住每次启动和停止应用程序时,您的工作内存将被丢弃,因此浏览器提供的 token 将不再匹配新的一个您的应用程序将在再次启动时检索(除非您再次清除了浏览器 cookie)。

MSAL 不再使用或支持

*cca.Users - 您必须使用 cca.GetAccountsAsync()。如果您有一个已部署的应用程序使用已弃用的 IUser 实现运行,则必须更改它。否则,在开发过程中,您的编译器会提示并且不允许您构建,因此您已经知道这一点。

关于c# - 代码 : TokenNotFound Message: User not found in token cache. 可能服务器已重新启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50171836/

相关文章:

c# - Xamarin - 删除 Android 中的 SearchBar 下划线

c# - 使用准无服务器 Web 架构(AJAX 模板魔法)确保安全 "private site areas"

asp.net-mvc - 计数选择列表项(计数 IEnumerable)

c# - 如何在 C# 中不使用 DataTable.Select() 对数据表进行排序?

C# 注册表子键双字值

c# - 在不访问 MouseEventArgs 的情况下获取鼠标状态?

C#,以编程方式查找任何过去的 BSOD 并获取代码

c# - Web API 中基于 token 的身份验证,无需任何用户界面

c# - 如何通过分析 API(ICofProfilerInfo 或任何 IMetadataImport 或任何其他方式)读取 System.Threading.Thread.ThreadState

asp.net-mvc - 自定义验证属性不适用于客户端,仅适用于服务器