Wcf: WCF client behind corporate proxy authentication failure - (407) Proxy Authentication Required.

Created on 4 Dec 2018  路  10Comments  路  Source: dotnet/wcf

I'm running into an issue when calling an external WCF behind a corporate proxy. In full .Net framework the following was placed in the app.config file which allowed the call to succeed:

  <system.net>
    <defaultProxy enabled="true" useDefaultCredentials="true">
      <proxy bypassonlocal="true" proxyaddress="http://address:port" />
    </defaultProxy>
  </system.net>

In .Net Core I have tried several ways of setting the proxy including setting the ProxyAddress in the BasicHttpBinding. When doing this I receive the (407) Proxy Authentication Required response. I believe this is due to not being able to set the useDefaultCredentials="true" portion in the binding.

In full .Net framework if I set useDefaultCredentials="false" I also receive the exact error of (407) Proxy Authentication Required.

Is there a way to set this to use default credentials when using a proxy?

Most helpful comment

Thanks. I kind of expected that the required parts are installed and used in the up-to date version either by the .net core 2.2 installation or VS 2019.

After telling the package-manager to lift all System.ServiceModel's from 4.4.4 to 4.5.3 the Exception vanishes and the proxy is used as configured.

According to ConnectedService.json the WCF in charge was 15.0.21025.787

Thanks!

All 10 comments

Be default WCF doesn't provide credentials to a proxy server for security reasons. You have to explicitly opt in to sending credentials. The relevant properties aren't available on BasicHttpBinding, instead you need to modify them on the HttpTransportBindingElement.
c# var httpBinding = new BasicHttpBinding(); // Set anything you need on the binding var customBinding = new CustomBinding(httpBinding); var htbe = customBinding.Element.Find<HttpTransportBindingElement>(); htbe.ProxyAddress = new Uri("http://address:port"); htbe.ProxyAuthenticationScheme = System.Net.AuthenticationSchemes.IntegratedWindowsAuthentication; // Or whatever authentication mechanism your proxy server uses htbe.UseDefaultWebProxy = false;
This will then use whatever credentials you have set for that authentication scheme in your ChannelFactory.ClientCredentials instance. For example, using IntegratedWindowsAuthentication, it would use ClientCredentials.Windows to get the credentials.

Thanks for the code snippet. if possible change Element to Elements

I've been doing something similar, but instead of generating a new binding i'd like to utilize a proxy class generated by Visual Studio 2019.

```c#
var b_custom = client.Endpoint.Binding as System.ServiceModel.Channels.CustomBinding;

if (b_custom != null)
{
var htbe = b_custom.Elements.Find();
htbe.ProxyAddress = new Uri(string.Format("http://{0}:{1}", address, port));
htbe.ProxyAuthenticationScheme = System.Net.AuthenticationSchemes.Anonymous; // Or whatever authentication mechanism your proxy server uses
htbe.UseDefaultWebProxy = false;
return;
}

however on windows 10 / core 2.2 that throws the following exception:

InvalidOperationException: When using a non-null Proxy, the WindowsProxyUsePolicy property must be set to WindowsProxyUsePolicy.UseCustomProxy.
```

That error message comes from WinHttpHandler. WCF stopped using that class directly quite a while ago and we now only reference HttpClientHandler. As of .NET Core 2.1, the default implementation is no longer WinHttpHandler and instead uses the newer SocketsHttpHandler. I suspect you are using a really old release of WCF. Can you make sure you are using the latest versions of System.ServiceModel.*. There was a bug in an earlier version around setting the proxy values on WinHttpHandler and I suspect you are running into that issue.

Thanks. I kind of expected that the required parts are installed and used in the up-to date version either by the .net core 2.2 installation or VS 2019.

After telling the package-manager to lift all System.ServiceModel's from 4.4.4 to 4.5.3 the Exception vanishes and the proxy is used as configured.

According to ConnectedService.json the WCF in charge was 15.0.21025.787

Thanks!

Thanks. I kind of expected that the required parts are installed and used in the up-to date version either by the .net core 2.2 installation or VS 2019.

After telling the package-manager to lift all System.ServiceModel's from 4.4.4 to 4.5.3 the Exception vanishes and the proxy is used as configured.

According to ConnectedService.json the WCF in charge was 15.0.21025.787

Thanks!

This solved it for me. I was also receiving the exception "When using a non-null Proxy, the WindowsProxyUsePolicy property must be set to WindowsProxyUsePolicy.UseCustomProxy.", which then disappeared once I updated all System.ServiceModel libs. Cheers!

I'm also getting the 407 issue. I'm not experienced with WCF so I'm probably doing something stupid, but when I try to use the fix from @mconnew the 407 error then changes to this one:

The 'IntegratedWindowsAuthentication' authentication scheme has been specified for the proxy on the HTTP factory. However, the factory only supports specification of exactly one authentication scheme. Valid authentication schemes are Digest, Negotiate, NTLM, Basic, or Anonymous.

This is my code :
``` c#
var oneMinute = new TimeSpan(0, 1, 0);

        var binding = new BasicHttpBinding();

        binding.Name = "DEEWR_Customer_OUTBinding";
        binding.AllowCookies = false;
        binding.SendTimeout = oneMinute;
        binding.ReceiveTimeout = new TimeSpan(0, 10, 0);
        binding.OpenTimeout = oneMinute;
        binding.CloseTimeout = oneMinute;
        binding.MaxBufferPoolSize = 2147483647;
        binding.MaxReceivedMessageSize = 2147483647;
        binding.TextEncoding = Encoding.UTF8;
        binding.TransferMode = TransferMode.Buffered;
        binding.BypassProxyOnLocal = false;
        binding.UseDefaultWebProxy = false;

        binding.ReaderQuotas.MaxDepth = 32;
        binding.ReaderQuotas.MaxStringContentLength = 5242880;
        binding.ReaderQuotas.MaxArrayLength = 16384;
        binding.ReaderQuotas.MaxBytesPerRead = 4096;
        binding.ReaderQuotas.MaxNameTableCharCount = 16384;

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

        var customBinding = new CustomBinding(binding);
        var htbe = customBinding.Elements.Find<HttpTransportBindingElement>();
        htbe.ProxyAddress = new Uri("http://proxy.dmz.ige:8080");
        htbe.ProxyAuthenticationScheme = System.Net.AuthenticationSchemes.IntegratedWindowsAuthentication;
        htbe.BypassProxyOnLocal = false;
        htbe.UseDefaultWebProxy = false;

        var endpointAddress = new EndpointAddress(EndpointUrl);

        var factory = new ChannelFactory<DEEWR_Customer_OUT>(customBinding, endpointAddress);
        factory.Credentials.ClientCertificate.SetCertificate(
            StoreLocation.LocalMachine,
            StoreName.My,
            X509FindType.FindBySubjectName,
            CertificateName);
        DEEWR_Customer_OUT serviceProxy = factory.CreateChannel();

```

Any suggestions for what I might be doing wrong?

Can you please provide the stack trace of the exception?

Looks like IntegratedWindowsAuthentication isn't supported. It's a flag that includes Negotiate and Ntlm so I've changed mine to use Ntlm instead - which has worked insomuch as it's moved me on to a different error, sigh.

Thanks for responding!

As you've already worked out, IntegratedWindowsAuthentication has a value of 6, Negotiate has a value of 2 and Ntlm has a value of 4. This means that IntegratedWindowsAuthentication isn't an authentication scheme in it's own right, it's a convenience value to mean Negotiate | Ntlm. We can't accept two different schemes being specified which is why IntegratedWindowsAuthentication isn't supported. The description for Negotiate is:

Negotiates with the client to determine the authentication scheme. If both client and server support Kerberos, it is used; otherwise, NTLM is used.

The only time when this won't work is when integrated Windows authentication isn't enabled on the proxy server but NTLM is. In which case specifying NTLM is needed. Otherwise Negotiate should generally work for you.

@mconnew hi seen your comment earlier up in the feed. I am having the same issue with wanting to provide a NetworkCredential object to a WCF generated service. This is made up of the domain, username & password as strings provided by config, how should I setup my binding and construct my service seem to have tried every which way and had no luck any help would be greatly appreciated.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

apdirexyon picture apdirexyon  路  5Comments

scottmchargue picture scottmchargue  路  3Comments

mconnew picture mconnew  路  5Comments

mconnew picture mconnew  路  5Comments

DotNetPart picture DotNetPart  路  6Comments