RickardPettersson / swish-api-csharp

Swish For Merchant API Client .Net Standard Library
MIT License
28 stars 13 forks source link

Using certificate as stream doesn't work #29

Closed anoop331 closed 1 month ago

anoop331 commented 8 months ago

When using certificate as a stream and when passed to the api, the code doesn't try to add the intermediate certificates to the certificate stores, as it would, if the certificate path is provided as the input. On windows, the intermediate certificates need to be added to the certificate store ( a cache), as explained in the SO link - https://stackoverflow.com/questions/61677247/can-a-p12-file-with-ca-certificates-be-used-in-c-sharp-without-importing-them-t

This is implemented and works for the flow, when the certificate path is provided as an input, but when stream is provided as the input it doesn't do that, the handshake with swish fails.

anoop331 commented 8 months ago

I made a fix, but I can't push my branch, to create a PR.

I think if you merge this code, to MCommerceClient.cs, the issue will be solved.

private void PrepareHttpClientAndHandler(out HttpClientHandler handler, out HttpClient client) { handler = new HttpClientHandler();

        if (_certificate != null)
        {
            if (_certificate.UseMachineKeySet)
            {
                if (string.IsNullOrEmpty(_certificate.Password))
                {
                    if (_certificate.SecureStringPassword != null)
                    {
                        var cert = new X509Certificate2(Misc.ReadFully(_certificate.CertificateAsStream),
                            _certificate.SecureStringPassword, X509KeyStorageFlags.MachineKeySet);

                        handler.ClientCertificates.Add(cert);
                    }
                    else
                    {
                        throw new Exception(
                            "Certificate password missing set wish needed to use with MachineKeySet");
                    }
                }
                else
                {
                    var cert = new X509Certificate2(Misc.ReadFully(_certificate.CertificateAsStream),
                        _certificate.Password, X509KeyStorageFlags.MachineKeySet);

                    handler.ClientCertificates.Add(cert);
                }
            }
            else
            {
                // Got help for this code on https://stackoverflow.com/questions/61677247/can-a-p12-file-with-ca-certificates-be-used-in-c-sharp-without-importing-them-t
                // using (X509Store store = new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser))

                var certBytes = string.IsNullOrEmpty(_certificate.CertificateFilePath) ?
                    Misc.ReadFully(_certificate.CertificateAsStream) :
                    File.ReadAllBytes(_certificate.CertificateFilePath);

                    //https://github.com/RickardPettersson/swish-api-csharp/issues/29
                    //Handle the certificate the same way if its from a file or a stream
                    SetCertificate(handler, certBytes, _certificate.Password);

            }
        }

        client = new HttpClient(new LoggingHandler(handler, _enableHTTPLog));
    }

    private static void SetCertificate(HttpClientHandler handler, byte[] certBytes, string password)
    {
        var certs = new X509Certificate2Collection();

        certs.Import(certBytes, password);

        foreach (var cert in certs)
        {
            if (cert.HasPrivateKey)
            {
                handler.ClientCertificates.Add(cert);
            }
            else
            {
                //Add the intermediate certificate to the trusted root store
                //which acts as a cache during the TLS handshake
                using var store = new X509Store(StoreName.CertificateAuthority,
                    StoreLocation.CurrentUser);
                store.Open(OpenFlags.ReadWrite);
                store.Add(cert);
            }
        }
    }
RickardPettersson commented 1 month ago

I added this code fixes in my latest update