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);
        }
Exemple #2
0
        /// <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>());
        }
Exemple #4
0
        /// <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>());
        }