private void UpdateCacheExpirationTimeForSecret(string key, CachedKeyVaultSecret cachedSecret, bool success)
        {
            if (!_keyVaultOptions.SecretRefreshIntervals.TryGetValue(key, out TimeSpan cacheExpirationTime))
            {
                if (_keyVaultOptions.DefaultSecretRefreshInterval.HasValue)
                {
                    cacheExpirationTime = _keyVaultOptions.DefaultSecretRefreshInterval.Value;
                }
            }

            if (cacheExpirationTime > TimeSpan.Zero)
            {
                if (success)
                {
                    cachedSecret.RefreshAttempts = 0;
                    cachedSecret.RefreshAt       = DateTimeOffset.UtcNow.Add(cacheExpirationTime);
                }
                else
                {
                    if (cachedSecret.RefreshAttempts < int.MaxValue)
                    {
                        cachedSecret.RefreshAttempts++;
                    }

                    cachedSecret.RefreshAt = DateTimeOffset.UtcNow.Add(cacheExpirationTime.CalculateBackoffTime(cachedSecret.RefreshAttempts));
                }
            }
        }
        public async Task <string> GetSecretValue(Uri secretUri, string key, CancellationToken cancellationToken)
        {
            string secretName    = secretUri?.Segments?.ElementAtOrDefault(2)?.TrimEnd('/');
            string secretVersion = secretUri?.Segments?.ElementAtOrDefault(3)?.TrimEnd('/');
            string secretValue   = null;

            if (_cachedKeyVaultSecrets.TryGetValue(key, out CachedKeyVaultSecret cachedSecret) &&
                (!cachedSecret.RefreshAt.HasValue || DateTimeOffset.UtcNow < cachedSecret.RefreshAt.Value))
            {
                return(cachedSecret.SecretValue);
            }

            SecretClient client = GetSecretClient(secretUri);

            if (client == null && _keyVaultOptions.SecretResolver == null)
            {
                throw new UnauthorizedAccessException("No key vault credential or secret resolver callback configured, and no matching secret client could be found.");
            }

            bool success = false;

            try
            {
                if (client != null)
                {
                    KeyVaultSecret secret = await client.GetSecretAsync(secretName, secretVersion, cancellationToken).ConfigureAwait(false);

                    secretValue = secret.Value;
                }
                else if (_keyVaultOptions.SecretResolver != null)
                {
                    secretValue = await _keyVaultOptions.SecretResolver(secretUri).ConfigureAwait(false);
                }

                cachedSecret = new CachedKeyVaultSecret(secretValue);
                success      = true;
            }
            finally
            {
                SetSecretInCache(key, cachedSecret, success);
            }

            return(secretValue);
        }
        private void SetSecretInCache(string key, CachedKeyVaultSecret cachedSecret, bool success = true)
        {
            if (cachedSecret == null)
            {
                cachedSecret = new CachedKeyVaultSecret();
            }

            UpdateCacheExpirationTimeForSecret(key, cachedSecret, success);
            _cachedKeyVaultSecrets[key] = cachedSecret;

            if (key == _nextRefreshKey)
            {
                UpdateNextRefreshableSecretFromCache();
            }
            else if ((cachedSecret.RefreshAt.HasValue && _nextRefreshTime.HasValue && cachedSecret.RefreshAt.Value < _nextRefreshTime.Value) ||
                     (cachedSecret.RefreshAt.HasValue && !_nextRefreshTime.HasValue))
            {
                _nextRefreshKey  = key;
                _nextRefreshTime = cachedSecret.RefreshAt.Value;
            }
        }