Тайм-аут Azure KeyVault Active Directory AcquireTokenAsync при асинхронном вызове

Я настроил Azure Keyvault в своем веб-приложении ASP.Net MVC, следуя примеру MicrosoftHello Key Vault образец приложения.

Azure KeyVault (Active Directory) AuthenticationResult по умолчанию имеет один час истечения. Поэтому через час вы должны получить новый токен аутентификации. KeyVault работает должным образом в течение первого часа после получения моего первого токена AuthenticationResult, но по истечении 1 часа он не может получить новый токен.

К сожалению, в моей производственной среде произошел сбой, и я понял это, поскольку я никогда не тестировал последние один час в разработке.

В любом случае, после более чем двух дней попыток выяснить, что не так с моим кодом keyvault, я нашел решение, которое исправляет все мои проблемы - удалить асинхронный код - но это кажется очень хакерским. Я хочу выяснить, почему это не сработало.

Мой код выглядит так:

public AzureEncryptionProvider() //class constructor
{
   _keyVaultClient = new KeyVaultClient(GetAccessToken);
   _keyBundle = _keyVaultClient
     .GetKeyAsync(_keyVaultUrl, _keyVaultEncryptionKeyName)
     .GetAwaiter().GetResult();
}

private static readonly string _keyVaultAuthClientId = 
    ConfigurationManager.AppSettings["KeyVaultAuthClientId"];

private static readonly string _keyVaultAuthClientSecret =
    ConfigurationManager.AppSettings["KeyVaultAuthClientSecret"];

private static readonly string _keyVaultEncryptionKeyName =
    ConfigurationManager.AppSettings["KeyVaultEncryptionKeyName"];

private static readonly string _keyVaultUrl = 
    ConfigurationManager.AppSettings["KeyVaultUrl"];

private readonly KeyBundle _keyBundle;
private readonly KeyVaultClient _keyVaultClient;

private static async Task<string> GetAccessToken(
    string authority, string resource, string scope)
{
   var clientCredential = new ClientCredential(
       _keyVaultAuthClientId, 
       _keyVaultAuthClientSecret);
   var context = new AuthenticationContext(
       authority, 
       TokenCache.DefaultShared);
   var result = context.AcquireToken(resource, clientCredential);
   return result.AccessToken;
}

Подпись метода GetAccessToken должна быть асинхронной для передачи в новый конструктор KeyVaultClient, поэтому я оставил подпись как асинхронную, но удалила ключевое слово await.

С ключевым словом await (так и должно быть в примере):

private static async Task<string> GetAccessToken(string authority, string resource, string scope)
{
   var clientCredential = new ClientCredential(_keyVaultAuthClientId, _keyVaultAuthClientSecret);
   var context = new AuthenticationContext(authority, null);
   var result = await context.AcquireTokenAsync(resource, clientCredential);
   return result.AccessToken;
}

Программа работает нормально при первом запуске. И в течение часа AcquireTokenAsync возвращает тот же самый оригинальный маркер аутентификации, который великолепен. Но как только срок действия токена истекает, AcquiteTokenAsync должен получить новый токен с новой датой истечения срока действия. И это не так - приложение просто зависает. Ошибка не возвращается, вообще ничего.

Поэтому вызов AcquireToken вместо AcquireTokenAsync решает проблему, но я понятия не имею, почему. Вы также заметите, что я передаю 'null' вместо 'TokenCache.DefaultShared' в конструктор AuthenticationContext в моем примере кода с помощью async. Это заставляет токен истечь немедленно, а не через час. В противном случае вам придется подождать час, чтобы воспроизвести поведение.

Мне удалось воспроизвести это снова в совершенно новом проекте MVC, поэтому я не думаю, что это имеет какое-либо отношение к моему конкретному проекту. Любое понимание будет оценено. Но сейчас я просто не использую async.

Ответы на вопрос(2)

Ваш ответ на вопрос