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

WCF client credentials are not used for proxy authentication #3551

Closed
Darkmace opened this issue Apr 11, 2019 · 7 comments · Fixed by #3818
Closed

WCF client credentials are not used for proxy authentication #3551

Darkmace opened this issue Apr 11, 2019 · 7 comments · Fixed by #3818
Assignees
Labels
Backlog Legitimate tasks of lower priority not in current dev schedule.

Comments

@Darkmace
Copy link

Darkmace commented Apr 11, 2019

When passing a WCF client request through a proxy requiring username/password authentication, the clients ClientCredentials are not used and it results in a "(407) Proxy Authentication Required" error. There does not appear to be any way in dotnet core to set whether to use default credentials or not for the proxy.

var binding = new BasicHttpBinding();

            binding.Security.Mode = BasicHttpSecurityMode.Transport;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;

            binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.Basic;
            binding.UseDefaultWebProxy = false;
            binding.ProxyAddress = new Uri("http://proxyURL.com:9293");

            using (var webClient = new CustomWCFClient(binding, "endpoint")))
            {
                webClient.ClientCredentials.ClientCertificate.Certificate = Certificate;
                webClient.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust;
                var xmlString = XmlString(xml);

                webClient.ClientCredentials.UserName.UserName = "username";
                webClient.ClientCredentials.UserName.Password = "password";

                var requestResult = webClient.sendMessage("anystring");
            }

A work around exists to get the proxy credentials working by creating a CustomBinding

var binding = new BasicHttpBinding();

            binding.Security.Mode = BasicHttpSecurityMode.Transport;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate; 
           
            var customBinding = new CustomBinding(binding);
            var httpElement = customBinding.Elements.Find<HttpTransportBindingElement>();
            httpElement.ProxyAddress = new Uri("http://proxyURL.com:9293");
            httpElement.ProxyAuthenticationScheme = AuthenticationSchemes.Basic;
            httpElement.UseDefaultWebProxy = false;

This results in the SendMessage request throwing an "The HTTP request was forbidden with client authentication scheme 'Anonymous" exception. There does not seem to be a way to configure the CustomBinding to use certificate authentication for the final endpoint.

This makes it seemingly impossible to interact with a WCF service that requires certificate authentication through a proxy requiring username/password authentication.

@Darkmace
Copy link
Author

After some further digging it seems that the "he HTTP request was forbidden with client authentication scheme 'Anonymous", is actually caused by the final endpoint returning "403 Ip forbidden". Which makes sense as it is protected by an IP whitelist.

So the custom binding may actually be working, which i will know once i am added to the whitelist.

But i would still have expected the BasicHttpBinding to have worked or have some way of specifying proxy credentials since you can specify an actual proxy, but apparently no way to authenticate against it.

A separate problem seems to be that the "403 Ip forbidden" error resulting in a "The HTTP request was forbidden with client authentication scheme 'Anonymous" exception. Which definitely led me astray and the exception is quite misleading and provides no way of seeing the actual "403 Ip forbidden" error.

@Lxiamail Lxiamail added this to the Future milestone Apr 24, 2019
@StephenBonikowsky StephenBonikowsky added the Backlog Legitimate tasks of lower priority not in current dev schedule. label May 23, 2019
@alexqlik
Copy link

alexqlik commented Aug 9, 2019

any updates on this issue?
I'm facing the same problem - no way to configure credentials for using with a proxy in WFC client..
It looks like it applies only to dotnet core. On windows (Microsoft .NET) same code works as expected.

@Darkmace
Copy link
Author

Darkmace commented Aug 12, 2019

This was the code i got working to work around this issue

var binding = new BasicHttpBinding();

            binding.Security.Mode = BasicHttpSecurityMode.Transport;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;

            //Wrap binding custombinding to route request through proxy with credential authentication
            var customBinding = new CustomBinding(binding);
            var httpElement = customBinding.Elements.Find<HttpTransportBindingElement>();
            httpElement.ProxyAddress = new Uri(Environment.GetEnvironmentVariable(ProxyURL));
            httpElement.ProxyAuthenticationScheme = AuthenticationSchemes.Basic;
            httpElement.UseDefaultWebProxy = false;

            using (var webClient = new TransparencyPlatformClient(customBinding, FinalEndpoint)
            {
                webClient.ClientCredentials.ClientCertificate.Certificate = Certificate;
                webClient.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust;
                var xmlString = XmlString(xml);

                webClient.ClientCredentials.UserName.UserName = ProxyUserName;
                webClient.ClientCredentials.UserName.Password = ProxyPassword;

                webClient.sendMessage(YourMessage);;
            }

The pitfall is that the proxy settings on BasicHttpBinding don't seem to be properly implemented as there is no way to get it to use the proper credentials. Which is way a CustomBinding has to be used.

@mconnew
Copy link
Member

mconnew commented Aug 13, 2019

It looks like there's a line of code missing in HttpTransportSecurity.ConfigureAuthentication where we copy the value from HttpTransportSecurity.ProxyCredentialType.

@mconnew
Copy link
Member

mconnew commented Aug 13, 2019

There's a fix in code review now

@StephenBonikowsky
Copy link
Member

@tjmoore
Copy link

tjmoore commented Nov 14, 2022

It's now possible to set the IWebProxy instance on HttpTransportBindingElement which may help as you can use DefaultProxy or define a proxy, which will use credentials if set.

#4563

e.g., This assumes the proxy uses basic credentials. The endpoint should in theory still use whatever client credentials you set though I've only tested with and endpoint using basic.

var binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.Transport;

var customBinding = new CustomBinding(binding);
var httpElement = customBinding.Elements.Find<HttpTransportBindingElement>();
httpElement.Proxy = HttpClient.DefaultProxy;

// Omitted, constructing client

client.Endpoint.Binding = customBinding;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Backlog Legitimate tasks of lower priority not in current dev schedule.
Projects
None yet
6 participants