private static (string, string) GetMetadataConfiguration(HttpDocumentRetriever documentRetriever, string metadataAddress, bool validateIssuer) { string?issuer = null; string?jwksUri = null; var config = documentRetriever.GetDocument(metadataAddress, CancellationToken.None); var reader = new Utf8JsonReader(config); if (!reader.Read() || reader.TokenType != JsonTokenType.StartObject) { throw new InvalidOperationException($"Invalid JSON document at '{metadataAddress}'."); } while (reader.Read() && reader.TokenType == JsonTokenType.PropertyName) { if (reader.ValueTextEquals(IssuerName)) { reader.Read(); issuer = reader.GetString(); if (jwksUri != null) { break; } } else if (reader.ValueTextEquals(JwksUriName)) { reader.Read(); jwksUri = reader.GetString(); if (issuer != null) { break; } } else { JsonParser.ConsumeJsonMember(ref reader); } } if (jwksUri is null) { throw new InvalidOperationException($"Invalid JSON document at '{metadataAddress}'. No 'jwks_uri' claim found."); } if (issuer is null) { throw new InvalidOperationException($"Invalid JSON document at '{metadataAddress}'. No 'issuer' claim found."); } // Not perfect as test, but we do not have the issuer here for the moment. if (validateIssuer && !metadataAddress.StartsWith(issuer)) { throw new InvalidOperationException($"The 'issuer' claim in the document '{metadataAddress}' is invalid."); } return(issuer, jwksUri); }
/// <summary> /// Retrieves a populated <see cref="OpenIdConnectConfiguration"/> given an address and an <see cref="DocumentRetriever"/>. /// </summary> /// <param name="address">address of the discovery document.</param> /// <param name="retriever">the <see cref="DocumentRetriever"/> to use to read the discovery document</param> /// <returns>A populated <see cref="OpenIdConnectConfiguration"/> instance.</returns> public static OpenIdConnectConfiguration Get(string address, HttpDocumentRetriever retriever, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(address)) { throw new ArgumentNullException(nameof(address)); } if (retriever == null) { throw new ArgumentNullException(nameof(retriever)); } var doc = retriever.GetDocument(address, cancellationToken); OpenIdConnectConfiguration openIdConnectConfiguration = OpenIdConnectConfiguration.FromJson(doc); return(openIdConnectConfiguration); }
/// <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>()); }