Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enrich http handler 18 #19

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

gratinierer
Copy link

An implementation to #18.
With that changes I'm able to manipulate the HttpClientHandler and e.g. fetch Certificates from the Windows CertStore and add them to the requests, so Authentication with Mutual SSL becomes possible:

        private ConnectionPreferences GetConnectionPreferences()
        {
            if (_connectionPreferences == null)
            {
                _connectionPreferences = new ConnectionPreferences
                {
                    HttpClientHandlerEnricher = h =>
                        SetCertificateConfiguration(h, InstanceConfiguration.KeyStoreCertificateConfiguration)
                };
            }
            return _connectionPreferences;
        }

        protected void SetCertificateConfiguration(HttpClientHandler handler,
            KeyStoreCertificate keyStoreCertificateConfiguration)
        {
            if (keyStoreCertificateConfiguration != null)
            {
                Log.Debug(
                    $"Looking for certificate '{keyStoreCertificateConfiguration.CertificateName}' in store '{keyStoreCertificateConfiguration.KeyStoreName}'");
                using X509Store store = new X509Store(keyStoreCertificateConfiguration.KeyStoreName,
                    StoreLocation.CurrentUser);
                store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
                var filteredCollection = store.Certificates
                    .Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, true).Find(
                        X509FindType.FindBySubjectName, keyStoreCertificateConfiguration.CertificateName, true);
                if (filteredCollection.Count != 1)
                {
                    throw new ClientCertificateSelectionException(
                        $"Expected exactly 1 Certificate with name '{keyStoreCertificateConfiguration.CertificateName}' in keystore '{keyStoreCertificateConfiguration.KeyStoreName}', but found {filteredCollection.Count}");
                }

                Log.Information($"Using Certificate '{filteredCollection[0].SubjectName.Name}'");
                handler.ClientCertificateOptions = ClientCertificateOption.Manual;
                handler.ClientCertificates.Add(filteredCollection[0]);
            }
        }

@gratinierer
Copy link
Author

Hi @erdomke ,
can you give me an information, if you plan to integrate that pull request?
Thanks and best regards
miro

@erdomke
Copy link
Owner

erdomke commented Jan 25, 2020

Sorry. I finally got around to this. I tried something different that I am hoping is a bit cleaner in afcddad. Would that meet your needs?

@gratinierer
Copy link
Author

Hi @erdomke,

cool, looks pretty much like the solution I wished I dared/was able to implement. During my test I got a little confused:
I had to add the following Line

      httpWebRequest.ClientCertificates = ClientCertificates;

to Innovator.Client.SyncClientHandler.CreateAndPrepareWebRequest.

Without adding this line, the httpClient seems to ignore the Certificates configured to the handler and not sending them to the server.
I think, that the combined usage HttpWebRequest and HttpClientHandler does not work as simple as in the minimal example i used for my tests:

        public static async Task Main(string[] args)
        {
            X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
            var filteredCollection = store.Certificates
                    .Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, true).Find(
                        X509FindType.FindBySubjectName, "aCertInTheTrusStore", true);
            var handler = new HttpClientHandler();
            handler.ClientCertificateOptions = ClientCertificateOption.Manual;
            handler.ClientCertificates.Add(filteredCollection[0]);
            var client = new HttpClient(handler);
            var response = await client.GetAsync("https://anUrl.com");
            Console.Out.WriteLine(await response.Content.ReadAsStringAsync());
            response.EnsureSuccessStatusCode();
        }

For my test with your code i build the lib with 'Innovator.Client.NetCore.csproj' on a core 3.1 environment.

Any idea how to get this working in a clean way?

Thanks for your great job!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants