Using BasicHttpSecurityMode.TransportWithMessageCredential in a partial (medium) trust enviroment - c#

I have an application which consumes a WCF web service, i log in to said service using credentials supplied by the company who maintain the service.
This is the code I created for binding the service.
I used svcutil.exe to generate a ClientSearchService.cs file and imported it into the project
BasicHttpBinding myBinding = new BasicHttpBinding();
myBinding.Name = "BasicHttpBinding_IClientSearch";
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
myBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
myBinding.MaxBufferSize = 524288;
myBinding.MaxBufferPoolSize = 524288;
myBinding.MaxReceivedMessageSize = 524288;
myBinding.ReaderQuotas.MaxDepth = 32;
myBinding.ReaderQuotas.MaxArrayLength = 524288;
myBinding.ReaderQuotas.MaxStringContentLength = 524288;
myBinding.Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential;
EndpointAddress endPointAddress = new EndpointAddress(serviceEndPointAddress);
ClientSearchClient myClient = new ClientSearchClient(myBinding, endPointAddress);
myClient.ClientCredentials.UserName.UserName = userName;
myClient.ClientCredentials.UserName.Password = userPass;
var request = new schemas.advancedcheck.co.uk.DriverChecksRequest();
request.FromDate = new DateTime(2014, 1, 1);
request.ToDate = DateTime.Now;
var response = myClient.GetDriverChecks(request);
If i execute this in a full trust environment i have no issues and the data I expect to see is returned successfully, however, where the code will be hosted will be a partial trust enviroment and when ran in a partial trust enviroment it throws this error:
The Binding with name BasicHttpBinding_IClientSearch failed validation because it contains a BindingElement with type System.ServiceModel.Channels.TransportSecurityBindingElement which is not supported in partial trust. Consider using BasicHttpBinding or WSHttpBinding, or hosting your application in a full-trust environment.
is there another method i can use to consume this web service in a partial trust enviroment?

Related

WCF erratically timing out despite binding timeout settings

My system is composed of a bunch of WCF services that can be used by various clients.
The first thing I do is to run the services in interactive mode (I have a console popping and letting me know the service is started).
I can then run a given client that excercises any of my WCF services. When instantiated the client create a channel and associated timeouts in the following way:
var ctx = new InstanceContext(TestCallbackProxy.Instance);
string baseAddress = Constants.ServiceBaseAddress;
var binding = new NetNamedPipeBinding();
binding.MaxConnections = 10;
binding.OpenTimeout = System.TimeSpan.FromMinutes(1);
binding.CloseTimeout = System.TimeSpan.FromMinutes(1);
binding.ReceiveTimeout = System.TimeSpan.FromMinutes(5);
binding.SendTimeout = System.TimeSpan.FromMinutes(5);
var channelFactory = new DuplexChannelFactory<ITestService>(ctx, binding, new EndpointAddress(baseAddress + serviceName));
// Create channel to a specified endpoint
_channel = channelFactory.CreateChannel() as ITestService;
Now, the service eventually times out when left unused for a while, which from my understanding is expected. ie. The channel will simply vanish/be discarded by the system if unused - Something to do with reusablility and optimisation I believe.
However, when trying to prove this theory and reducing all the timeouts, I cannot get the service to break. ie. Should the service not timeout/break when trying to use it when left alone for more than 30sec? Used timeouts are:
binding.OpenTimeout = System.TimeSpan.FromMinutes(0.5);
binding.CloseTimeout = System.TimeSpan.FromMinutes(0.5);
binding.ReceiveTimeout = System.TimeSpan.FromMinutes(0.5);
binding.SendTimeout = System.TimeSpan.FromMinutes(0.5);
I think the reason is that you should be setting your timeouts on the service side, where you are setting up your hosts and defining endpoints, not on the client side. Here is an example:
var binding = new NetNamedPipeBinding();
binding.MaxConnections = 10;
binding.OpenTimeout = TimeSpan.FromMinutes(0.5);
binding.CloseTimeout = TimeSpan.FromMinutes(0.5);
binding.ReceiveTimeout = TimeSpan.FromMinutes(0.5);
binding.SendTimeout = TimeSpan.FromMinutes(0.5);
// Compose URIs
Uri uriBase = new Uri(baseAddress);
Uri uri = new Uri(baseAddress + something);
Uri uriMex = new Uri(baseAddress + something + "/mex");
// Create End Points
SomeHost = new CustomServiceHost(typeof(TestService), uriBase);
SomeHost.AddServiceEndpoint(typeof(ITestService), binding, uri);
SomeHost.AddServiceEndpoint(typeof(IMetadataExchange), binding, uriMex);
// Open the ServiceHost
SomeHost.Open();
Now you should see you service dying after 30sec.

Secured selfhosted WCF service: load certificate from file

I have a selfhosted WCF service publishing a REST web API. The service is configured programmatically, and currently is correctly working via HTTP.
Now I need to make it work over HTTPS, with an authentication based on certificate file.
I know the suggested way to do this is installing the certificate in the Windows Certificate Store on the server machine, but this way is not possible in my circumstances.
I need to load the certificate from the file.
After some resarches, I wrote my code, but when I try accessing the web service, a System.ServiceModel.CommunicationException is thrown, with the message:
An error occurred while making the HTTP request to ... This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. This could also be caused by a mismatch of the security binding between the client and the server.
Here's my code for the server side:
_host = new WebServiceHost(_hostedService, Uri);
//Configuring the webHttpBinding settings
var httpBinding = new WebHttpBinding();
httpBinding.Security.Mode = WebHttpSecurityMode.Transport;
httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
httpBinding.SendTimeout = new TimeSpan(0, 5, 0);
httpBinding.MaxBufferSize = 2147483647;
httpBinding.MaxBufferPoolSize = 2147483647;
httpBinding.MaxReceivedMessageSize = 2147483647;
httpBinding.ReaderQuotas.MaxDepth = 2147483647;
httpBinding.ReaderQuotas.MaxStringContentLength = 2147483647;
httpBinding.ReaderQuotas.MaxArrayLength = 2147483647;
httpBinding.ReaderQuotas.MaxBytesPerRead = 2147483647;
httpBinding.ReaderQuotas.MaxNameTableCharCount = 2147483647;
//Add the endpoint with the webHttpBinding settings to the WebServiceHost configuration
_host.AddServiceEndpoint(typeof(IService), httpBinding, Uri);
ServiceDebugBehavior stp = _host.Description.Behaviors.Find<ServiceDebugBehavior>();
stp.HttpHelpPageEnabled = false;
ServiceBehaviorAttribute sba = _host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
sba.InstanceContextMode = InstanceContextMode.Single;
ServiceMetadataBehavior smb = new ServiceMetadataBehavior() { HttpsGetEnabled = true };
_host.Description.Behaviors.Add(smb);
X509Certificate2 trustedCertificate = new X509Certificate2("certificate.pfx", "password");
_host.Credentials.ServiceCertificate.Certificate = trustedCertificate;
_host.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
Here's my code for the client side:
var httpBinding = new WebHttpBinding();
httpBinding.Security.Mode = WebHttpSecurityMode.Transport;
httpBinding.Security.Transport = new HttpTransportSecurity() { ClientCredentialType = HttpClientCredentialType.Certificate };
var httpUri = new Uri(String.Format("https://{0}:{1}", ipAddress, tcpPort));
var httpEndpoint = new EndpointAddress(httpUri);
var newFactory = new ChannelFactory<IService>(httpBinding, httpEndpoint);
newFactory.Endpoint.Behaviors.Add(new WebHttpBehavior());
X509Certificate2 trustedCertificate = new X509Certificate2("certificate.pfx", "password"); //SSL
newFactory.Credentials.ClientCertificate.Certificate = trustedCertificate;
var channel = newFactory.CreateChannel();
var response = channel.Ping("helo");
The Exception is thrown on the last line (channel.Ping("helo")).
I need to make it work WITHOUT installing the certificate on the server machine.
Thank you very much.
Bye.
As far as I know, when we host the self-hosted WCF service over Https, whatever way we use (load certificate file or configure the certificate via Windows Certificate Store), it is impossible to make the service works normally. The only way we need to do is binding the certificate manually by using the following command.
netsh http add sslcert ipport=0.0.0.0:8000 certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF}
Here is official document, wish it is useful to you.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-configure-a-port-with-an-ssl-certificate
https://learn.microsoft.com/en-us/windows/desktop/http/add-sslcert
Here are some examples were ever written by me.
WCF Service over HTTPS without IIS, with SSL Certificate from CERT and KEY strings or files
Chrome (v71) ERR_CONNECTION_RESET on Self Signed localhost on Windows 8 Embedded
Feel free to let know if there is anything I can help with.

Calling a SAP ME web Service in wcf web service

I have a soap web service (sap me web service), I generated the wcf proxy. no problem, I developed a WinForms application no problem
Now i try to use it in my wcf service (webHttpBinding binding in domain network) but i have an authentication error:
WCF - The HTTP request is unauthorized with client authentication scheme 'Basic'. The authentication header received from the server was 'Basic realm="mySoapServiceName"
It is IIS User problem ?
Thanks
SAP is using basic auth. You need to specify the username and password after you have created the proxy, for example:
proxy.Credentials.UserName.UserName = "joe";
proxy.Credentials.UserName.Password = "doe";
BasicHttpBinding myBinding = new BasicHttpBinding();
myBinding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
EndpointAddress ea = new EndpointAddress("url de mon web service soap");
SfcServices.SFCProcessingInClient myClient = new SfcServices.SFCProcessingInClient(myBinding, ea);
myClient.ClientCredentials.UserName.UserName = _MESwsLogin;
myClient.ClientCredentials.UserName.Password = _MESwsPassword;
SfcServices.SFCStateRequestMessage_sync srm = new SfcServices.SFCStateRequestMessage_sync();
SfcServices.SFCStateRequest sr = new SfcServices.SFCStateRequest();
srm.SfcStateRequest = sr;
sr.SiteRef = new SfcServices.SiteRef();
sr.SiteRef.Site = _MESsite;
sr.SfcRef = new SfcServices.SFCRef();
sr.SfcRef.Sfc = "12345678903";
sr.includeSFCStepList = true;
SfcServices.SFCStateConfirmationMessage_sync response = myClient.FindStateByBasicData(srm);
strOrdreFab = response.SfcStateResponse.SFCStatus.Sfc.ShopOrderRef.ShopOrder;
strCodeProduit = response.SfcStateResponse.SFCStatus.Sfc.ItemRef.Item;
strIndice = response.SfcStateResponse.SFCStatus.Sfc.ItemRef.Revision;

Does Mono\Xamarin support Basic auth?

I'm trying to run this code with Xamarin.Android but it falls down on last line(System.Net.WebException: There was an error on processing web request: Status code 401(Unauthorized)):
var binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
var endPointUri = new Uri(#"http://192.168.1.241/edo/Euphrates.svc/ILogonService-Basic");
var factory = new ChannelFactory<ILogonService>(binding, new EndpointAddress(endPointUri));
factory.Credentials.UserName.UserName = "test";
factory.Credentials.UserName.Password = "test";
ILogonService service = factory.CreateChannel();
Console.WriteLine(service.Logon("test"));
On windows console app everything works very well.
You can use basic authentication in an url in Xamarin:
https://username:password#www.example.com/webcallback?foo=bar

SharePoint 2010 - Using SOAP web service

I've added a reference to a SOAP service in my VS2010 project. I have a form that registers users for a newsletter. For me to get this form to work, I have to edit the SharePoint server's web.config and add in the SOAP bindings. If I don't do that and add it into my project's app.config, the server gives an error:
Could not find default endpoint element that references contract 'contractAPI.Soap' in the ServiceModel client configuration section.
How can I bypass the web.config and use the app.config to configure the SOAP service or set this up programmatically using C#?
You can set the bindings in your code like this:
internal static WServiceSoapClient CreateWebServiceInstance()
{
BasicHttpBinding binding = new BasicHttpBinding();
binding.SendTimeout = TimeSpan.FromMinutes(1);
binding.OpenTimeout = TimeSpan.FromMinutes(1);
binding.CloseTimeout = TimeSpan.FromMinutes(1);
binding.ReceiveTimeout = TimeSpan.FromMinutes(10);
binding.AllowCookies = false;
binding.BypassProxyOnLocal = false;
binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
binding.MessageEncoding = WSMessageEncoding.Text;
binding.TextEncoding = System.Text.Encoding.UTF8;
binding.TransferMode = TransferMode.Buffered;
binding.UseDefaultWebProxy = true;
return new WServiceSoapClient(binding, new EndpointAddress("http://yourservice.com/service.asmx"));
}

Categories

Resources