Reputation: 2521
I have a C# app which is calling a WCF service via a proxy server. Both the proxy and the WCF service require (different) credentials. I am using the svcutil-generated proxy classes to access the WCF service.
When I switch off the proxy server's requirement for credentials then I can access the WCF service fine so all that I want is to know where to apply the credentials for the proxy server (I'm using Fiddler in my dev environment).
I've read various posts which say to set the credentials in client.ClientCredentials
and this seems to work for either the proxy server credentials OR the WCF service credentials but I can't store both.
If I put the proxy server credentials in client.ClientCredentials
then the request hits the WCF service but then gets rejected.
If I put the WCF service credentials in client.ClientCredentials
then the request does not get past the proxy server.
Is there a way to supply two different sets of credentials so I can get authenticated by the proxy server and the WCF service? I need to do this in code, not in the config file.
Code is below:
public class Runner
{
public int GetAvailableFacilities(int timeoutInSeconds, string uri, string userName, string password)
{
FacilitySearchServiceClient client = null;
try
{
client = SetClient(timeoutInSeconds, uri, userName, password, client);
string outputMessage = null;
int[] availableFacilities = client.GetAvailableFacilities(out outputMessage);
return availableFacilities.Length;
}
finally
{
if (client != null)
{
client.Close();
}
}
}
private FacilitySearchServiceClient SetClient(int timeoutInSeconds, string uri, string wcfServiceUserName, string wcfServicePassword, FacilitySearchServiceClient client)
{
string proxyServerUsername = "1";//Fiddler
string proxyServerPassword = "1";//Fiddler
client = new FacilitySearchServiceClient(ConfigureServiceBinding(timeoutInSeconds), new EndpointAddress(uri));
//If this is the only uncommented call to SetServiceCredentials the proxy server transmits the request
//to the wcf service which then rejects the authentication attempt.
SetServiceCredentials(client.ClientCredentials, proxyServerUsername, proxyServerPassword);
//If this is the only uncommented call to SetServiceCredentials the proxy server rejects the authentication attempt,
//resulting in an EndpointNotFoundException.
SetServiceCredentials(client.ClientCredentials, wcfServiceUserName, wcfServicePassword);
return client;
}
protected static void SetServiceCredentials(ClientCredentials credentials, string userName, string password)
{
credentials.UserName.UserName = userName;
credentials.UserName.Password = password;
}
protected CustomBinding ConfigureServiceBinding(int timeoutInSeconds)
{
CustomBinding binding = new CustomBinding();
SecurityBindingElement sbe = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
sbe.IncludeTimestamp = false;
sbe.EnableUnsecuredResponse = true;
sbe.AllowInsecureTransport = true;
binding.Elements.Add(sbe);
binding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, System.Text.Encoding.UTF8));
binding.Elements.Add(CreateHttpsBindingElement(Const.ProxyServerUrl));
return binding;
}
/// <summary>
/// Sets up the element needed for the web service call.
/// </summary>
private static HttpsTransportBindingElement CreateHttpsBindingElement(string proxyUri)
{
HttpsTransportBindingElement tpt = new HttpsTransportBindingElement();
tpt.TransferMode = TransferMode.Streamed;
tpt.MaxReceivedMessageSize = Int32.MaxValue;
tpt.MaxBufferSize = Int32.MaxValue;
tpt.AuthenticationScheme = System.Net.AuthenticationSchemes.Anonymous;
if (string.IsNullOrEmpty(proxyUri) == false)
{
tpt.ProxyAddress = new Uri(proxyUri);
tpt.UseDefaultWebProxy = false;
tpt.ProxyAuthenticationScheme = System.Net.AuthenticationSchemes.Basic;
}
return tpt;
}
}
Upvotes: 1
Views: 1041
Reputation: 181
I ran in to this exact same problem a few months back. The problem is the WCF client proxy does not expose a separate property for specifying proxy server credentials like say, the HttpWebRequest
object which exposes a proxy property of type System.Net.WebProxy
. In that case you could just use the Credentials
property of the System.Net.WebProxy
type to achieve what you are trying to do. In your case you can do this for your WCF client by setting the proxy credentials for all the web requests made by your .NET application by modifying the Application_Start method in Global.asax.cs (assuming that your client is also a web app). Otherwise you could just use this code in the appropriate startup method of your client application.
protected void Application_Start(Object sender, EventArgs e)
{
var proxy = new WebProxy("myproxyservername", <myproxyPort>) { Credentials = new System.Net.NetworkCredential("yourproxyusername", "yourproxypassword") };
WebRequest.DefaultWebProxy = proxy;
}
Upvotes: 1