public static ListedCapabilityStatement BuildRestResourceComponent(this ListedCapabilityStatement statement, ResourceType resourceType, Action <ListedResourceComponent> componentBuilder)
        {
            EnsureArg.IsNotNull(statement, nameof(statement));
            EnsureArg.IsNotNull(componentBuilder, nameof(componentBuilder));

            var restComponent = statement.GetListedRestComponent();

            var restNode = restComponent
                           .Resource
                           .FirstOrDefault(x => x.Type == resourceType);

            if (restNode == null)
            {
                restNode = new ListedResourceComponent
                {
                    Type    = resourceType,
                    Profile = new ResourceReference(ResourceIdentity.Core(resourceType.ToString()).AbsoluteUri),
                };
                restComponent.Resource.Add(restNode);
            }

            componentBuilder(restNode);

            return(statement);
        }
        public static ListedCapabilityStatement AddProxyOAuthSecurityService(this ListedCapabilityStatement statement, IUrlResolver urlResolver, string authorizeRouteName, string tokenRouteName)
        {
            EnsureArg.IsNotNull(statement, nameof(statement));
            EnsureArg.IsNotNull(urlResolver, nameof(urlResolver));
            EnsureArg.IsNotNullOrWhiteSpace(authorizeRouteName, nameof(authorizeRouteName));
            EnsureArg.IsNotNullOrWhiteSpace(tokenRouteName, nameof(tokenRouteName));

            var restComponent = statement.GetListedRestComponent();
            var security      = restComponent.Security ?? new CapabilityStatement.SecurityComponent();

            security.Service.Add(Constants.RestfulSecurityServiceOAuth);
            var tokenEndpoint         = urlResolver.ResolveRouteNameUrl(tokenRouteName, null);
            var authorizationEndpoint = urlResolver.ResolveRouteNameUrl(authorizeRouteName, null);

            var smartExtension = new Extension()
            {
                Url       = Constants.SmartOAuthUriExtension,
                Extension = new List <Extension>
                {
                    new Extension(Constants.SmartOAuthUriExtensionToken, new FhirUri(tokenEndpoint)),
                    new Extension(Constants.SmartOAuthUriExtensionAuthorize, new FhirUri(authorizationEndpoint)),
                },
            };

            security.Extension.Add(smartExtension);
            restComponent.Security = security;
            return(statement);
        }
        public static ListedCapabilityStatement AddProxyOAuthSecurityService(this ListedCapabilityStatement statement, System.Uri metadataUri)
        {
            EnsureArg.IsNotNull(statement, nameof(statement));

            var restComponent = statement.GetListedRestComponent();
            var security      = restComponent.Security ?? new CapabilityStatement.SecurityComponent();

            security.Service.Add(Constants.RestfulSecurityServiceOAuth);
            var baseurl               = metadataUri.Scheme + "://" + metadataUri.Authority;
            var tokenEndpoint         = $"{baseurl}/AadSmartOnFhirProxy/token";
            var authorizationEndpoint = $"{baseurl}/AadSmartOnFhirProxy/authorize";

            var smartExtension = new Extension()
            {
                Url       = Constants.SmartOAuthUriExtension,
                Extension = new List <Extension>
                {
                    new Extension(Constants.SmartOAuthUriExtensionToken, new FhirUri(tokenEndpoint)),
                    new Extension(Constants.SmartOAuthUriExtensionAuthorize, new FhirUri(authorizationEndpoint)),
                },
            };

            security.Extension.Add(smartExtension);
            restComponent.Security = security;
            return(statement);
        }
        public static ListedCapabilityStatement AddOAuthSecurityService(this ListedCapabilityStatement statement, string authority, IHttpClientFactory httpClientFactory, ILogger logger)
        {
            EnsureArg.IsNotNull(statement, nameof(statement));
            EnsureArg.IsNotNull(authority, nameof(authority));
            EnsureArg.IsNotNull(httpClientFactory, nameof(httpClientFactory));

            var restComponent = statement.GetListedRestComponent();
            var security      = restComponent.Security ?? new CapabilityStatement.SecurityComponent();

            security.Service.Add(Constants.RestfulSecurityServiceOAuth);

            var openIdConfigurationUrl = $"{authority}/.well-known/openid-configuration";

            HttpResponseMessage openIdConfigurationResponse;

            using (var httpClient = httpClientFactory.CreateClient())
            {
                try
                {
                    openIdConfigurationResponse = httpClient.GetAsync(new Uri(openIdConfigurationUrl)).GetAwaiter().GetResult();
                }
                catch (Exception ex)
                {
                    logger.LogWarning(ex, $"There was an exception while attempting to read the OpenId Configuration from \"{openIdConfigurationUrl}\".");
                    throw new OpenIdConfigurationException();
                }
            }

            if (openIdConfigurationResponse.IsSuccessStatusCode)
            {
                var openIdConfiguration = JObject.Parse(openIdConfigurationResponse.Content.ReadAsStringAsync().GetAwaiter().GetResult());

                string tokenEndpoint, authorizationEndpoint;

                try
                {
                    tokenEndpoint         = openIdConfiguration["token_endpoint"].Value <string>();
                    authorizationEndpoint = openIdConfiguration["authorization_endpoint"].Value <string>();
                }
                catch (Exception ex)
                {
                    logger.LogWarning(ex, $"There was an exception while attempting to read the endpoints from \"{openIdConfigurationUrl}\".");
                    throw new OpenIdConfigurationException();
                }

                var smartExtension = new Extension()
                {
                    Url       = Constants.SmartOAuthUriExtension,
                    Extension = new List <Extension>
                    {
                        new Extension(Constants.SmartOAuthUriExtensionToken, new FhirUri(tokenEndpoint)),
                        new Extension(Constants.SmartOAuthUriExtensionAuthorize, new FhirUri(authorizationEndpoint)),
                    },
                };

                security.Extension.Add(smartExtension);
            }
            else
            {
                logger.LogWarning($"The OpenId Configuration request from \"{openIdConfigurationUrl}\" returned an {openIdConfigurationResponse.StatusCode} status code.");
                throw new OpenIdConfigurationException();
            }

            restComponent.Security = security;
            return(statement);
        }