/// <inheritsdoc /> private Jwk[] GetKeys(JwtHeaderDocument header, string metadataAddress) { if (_disposed) { ThrowHelper.ThrowObjectDisposedException(typeof(JwksHttpKeyProvider)); } var kid = header.Kid; long now = EpochTime.UtcNow; if (_currentJwks != null && _syncAfter > now) { return(_currentJwks.GetKeys(kid)); } if (_syncAfter <= now) { _refreshLock.Wait(); try { var value = _documentRetriever.GetDocument(metadataAddress, CancellationToken.None); var refreshedJwks = Jwks.FromJson(Issuer, value); Jwks.PublishJwksRefreshed(refreshedJwks); _currentJwks = refreshedJwks; _syncAfter = now + AutomaticRefreshInterval; } catch { _syncAfter = now + (AutomaticRefreshInterval < RefreshInterval ? AutomaticRefreshInterval : RefreshInterval); throw; } finally { _refreshLock.Release(); } } if (_currentJwks != null) { return(_currentJwks.GetKeys(kid)); } ThrowHelper.ThrowInvalidOperationException_UnableToObtainKeysException(metadataAddress); return(Array.Empty <Jwk>()); }
/// <inheritsdoc /> protected Jwk[] GetKeys(JwtHeader header, string metadataAddress) { if (_disposed) { ThrowHelper.ThrowObjectDisposedException(GetType()); } var kid = header.Kid; var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); if (_currentKeys != null && _syncAfter > now) { return(_currentKeys.GetKeys(kid)); } if (_syncAfter <= now) { _refreshLock.Wait(); try { var value = _documentRetriever.GetDocument(metadataAddress, CancellationToken.None); _currentKeys = Jwks.FromJson(value); _syncAfter = now + AutomaticRefreshInterval; } catch { _syncAfter = now + (AutomaticRefreshInterval < RefreshInterval ? AutomaticRefreshInterval : RefreshInterval); throw; } finally { _refreshLock.Release(); } } if (_currentKeys != null) { return(_currentKeys.GetKeys(kid)); } ThrowHelper.ThrowInvalidOperationException_UnableToObtainKeysException(metadataAddress); return(Array.Empty <Jwk>()); }
/// <summary> /// Returns a task which contains a string converted from remote document when completed, by using the provided address. /// </summary> /// <param name="address">Location of document</param> /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation. <see cref="CancellationToken"/></param> /// <returns>Document as a string</returns> public byte[] GetDocument(string address, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(address)) { throw new ArgumentNullException(nameof(address)); } if (!IsHttps(address) && RequireHttps) { ThrowHelper.ThrowArgumentException_RequireHttpsException(address); } if (_disposed) { ThrowHelper.ThrowObjectDisposedException(GetType()); } using HttpResponseMessage response = _httpClient.GetAsync(address, cancellationToken).ConfigureAwait(false).GetAwaiter().GetResult().EnsureSuccessStatusCode(); return(response.Content.ReadAsByteArrayAsync().ConfigureAwait(false).GetAwaiter().GetResult()); }