Глядя на код, кажется, что некоторые кусочки логики отсутствуют. Например, вы получили метод
public async Task<string> GetUserAccessTokenAsync(string userId)
но я не вижу, как это называется. Кроме того, я не вижу кода для извлечения токена из Azure AD. Наконец, сообщение об ошибке, которое вы упоминаете
Код: TokenNotFound Сообщение: пользователь не найден в кэше токена. Возможно, сервер был перезапущен.
Похоже на ошибку, которую вы выдаете
if (!cca.Users.Any()) throw new ServiceException(new Error
{
Code = "TokenNotFound",
Message = "User not found in token cache. Maybe the server was restarted."
});
Поскольку код не завершен, я постараюсь сделать предположение о том, что может пойти не так.
Во-первых, если вы используете MSAL.Net, то этап получения токена отсутствует.
Общий поток (Использование GetTokenByAuthorizationCodeAsync()
)
- Клиент бросает вызов пользователю
- Пользователь перенаправляется и входит в систему
- Вызывается обратный вызов, и клиент получает
code
от процесса входа в систему
- Передайте код в
GetTokenByAuthorizationCodeAsync()
, чтобы получить id_token и, в зависимости от разрешений, токен доступа.
GetTokenByAuthorizationCodeAsync()
будет хранить токен в кеше
который был предоставлен ConfidentialClientApplication
- Получить токен из кэша с помощью
AcquireTokenSilentAsync()
- Если нам не удастся получить токен из кэша с помощью
AcquireTokenSilentAsync()
, мы запросим новый через
AcquireTokenAsync()
Большая часть этого потока, кажется, имеет место в вашем коде, но, возможно, вы упускаете фактическое получение токена. Поскольку токен не извлекается, пользователь не добавляется в ConfidentialClientApplication
, что означает, что cca.Users.Any()
возвращает false, что приводит к ServiceError
Предполагая, что весь поток на месте, и вы на самом деле получаете токен, мое второе предположение было бы, что _memoryCache
отличаются. _MemoryCache, в котором вы сохранили свой токен, отличается от того, который вы используете для автоматического получения токена.
Я бы порекомендовал прочитать документацию о получении токена , чтобы определить, какой тип поиска подходит для вашего приложения.
РЕДАКТИРОВАТЬ
На самом деле, я предполагаю, что ваш код вдохновлен этим примером .
Что особенно интересно, эта часть
public GraphServiceClient GetAuthenticatedClient(string userId)
{
_graphClient = new GraphServiceClient(new DelegateAuthenticationProvider(
async requestMessage =>
{
// Passing tenant ID to the sample auth provider to use as a cache key
var accessToken = await _authProvider.GetUserAccessTokenAsync(userId);
...
}
return _graphClient;
}
Кажется, что происходит то, что вызов var user = await graphClient.Users.Request().GetAsync();
вызывает делегат, предоставленный GraphServiceClient. Это, в свою очередь, вызывает _authProvider.GetUserAccessTokenAsync(userId);
, что приводит нас к методу public async Task<string> GetUserAccessTokenAsync(string userId)
. Скорее всего, наша ошибка происходит из-за отсутствия пользователей в ConfidentialClientApplication.Users
коллекции
Надеюсь, это поможет!