Change WebService Endpoint from HTTP to HTTPS - c#

I'm really new to .NET and I have come to a roadblock (I guess).
I have a project that needs changing one address for another service we use, this address changed from HTTP to HTTPS.
My question is, for this change, do I need to change the code of the method that invokes the request, so I load the certificate in there, or do I just change the endpoint config?
I've tried the endpoint config security binding from None to TransportWithMessageCredential, also loading the certificate to the machine repository, but I'm not sure how do I specify what certificate I want to send.

I guess you are using BasicHttpBinding right now, and need to change from a HTTP endpoint to a HTTPS endpoint that requires validation through X509 certificate. I'm assuming you're using C#.
If you're using any version of .NET Framework older than 4.5, you can do:
var binding = new BasicHttpBinding(BasicHttpsSecurityMode.Transport);
If you are using .NET Framework 4.5 or newer version, you can do like this:
var binding = new BasicHttpsBinding();
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
Assuming you've imported the WebService definition deriving from System.ServiceModel.ClientBase (like when you right-click the project in Visual Studio and choose Add > Service Reference), you can do something like this:
var address = new EndpointAddress(serviceUrl);
var wsClient = new ServiceReference1.YourServiceClient(binding, address);
// x509Cert is a variable of type 'X509Certificate2'.
wsClient.ClientCredentials.ClientCertificate.Certificate = x509Cert;
// Take a look at: https://stackoverflow.com/a/49303859/
wsClient.Open();
wsClient.CallTheService();
wsClient.Close();

Related

How to generate web service client from WSDL (like a pro), when address is changing frequently?

I have to consume some service on ESB which has addresses:
for dev env: http://esbdev.com:11111/ws/ir.channel.aaa.pub.ws:ConsumeMeV1
for test env: https://esbtest.com:22222/ws/ir.channel.aaa.ws:DoAmazingCalc
Functionality is the same.
Can I somehow have only one common code (to rule them all) in c# generated from WSDL and manipulate to which env I’m connecting by some config?
And can i switch freely between http on dev and https on test environment?
Now I’m calling it on dev like:
using (ConsumeMeV1_PortTypeClient client = new ConsumeMeV1_PortTypeClient(this.EsbEndpointBinding, this.EsbEndpointAddress))
But there is dev name hardcoded - how should i map ConsumeMeV1 to DoAmazingCalc on test?
On test I'm calling it like:
using (DoAmazingCalc_PortTypeClient client = new DoAmazingCalc_PortTypeClient(this.EsbEndpointBinding, this.EsbEndpointAddress))
Can I generate common clases like:
using (BestServiceNameClient client = new BestServiceNameClient(this.EsbEndpointBinding, this.EsbEndpointAddress))
The best option for me is to get endpoint/names config from database and inject to clinet class - but how?
Ok, I know where the minuses come from.
No part of the address matters as long as the functionality underneath it does not change. So both generated classes will allow you to use them with each of the given addresses. I note that these obvious things are like that only when you know about it, so I'm sorry that no one even wrote a word about it.
However, when it comes to https, it depends on the BasicHttpBinding.Security.Mode settings. You can set Transport for https and TransportCredentialOnly for http. The corresponding value can be saved and retrieved from the database or other configuration together with the user and password.
I use the above with the setting:
BasicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

How do i Set the System.ServiceModel.ClientBase<TChannel> to Ignore CERT Errors

I am moving an application that communicates with a WCF service from .net 4.8 to net5 i ran the utility SvcUtil.exe (importing a WDSL File) which generated the Reference.cs file which created the classes and object from the WSDL file. In net5 it is now using the System.ServiceModel.ClientBase class to interact with the WCF Service, where as in net48 it was using 'System.Web.Services.Protocols.SoapHttpClientProtocol'. Code compiles but there remains two problems that I'm experiencing right now that i cannot seem to find the answer for using the new 'System.ServiceModel.ClientBase' implementation generated by the SvcUtil.exe tool.
When the connection is trying to be established i am always getting the following Exception:
{"Could not establish trust relationship for the SSL/TLS secure channel with authority 'xxx.xxx.xxx.xxx'."} InnerException => {"The SSL connection could not be established, see inner exception."} InnerException => {"The remote certificate is invalid according to the validation procedure: RemoteCertificateNameMismatch, RemoteCertificateChainErrors"}
Also the in the net48 version i store the cookie in the cookie container like So:
Cookie cookie = new Cookie(cookieParts[0], cookieParts[1],
serviceUri.LocalPath, serviceUri.Host);
cookie.Expires = DateTime.Now.AddHours(1);
_xieServiceRef.CookieContainer = new CookieContainer();
_xieServiceRef.CookieContainer.Add(serviceUri, cookie);
My problem is that for one in net48 to tell the service to ignore all cert errors we execute the following code
ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => { return true; }
From anywhere in the app and we bypass those errors. But in net5 you have to approach it differently and the only example is given using the HttpClient class and you create the HttpClient with a defined HttpClientHandler callback as in the example below this will ignore the CERT errors just as the code above for net48.
var EndPoint = "https://192.168.0.1/api";
var httpClientHandler = new HttpClientHandler();
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) =>
{
return true;
};
httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(EndPoint) };
In using the SvcUtil.exe generated code with the use of the ClientBase class as a means of interaction with the WCF Service, I cannot find methods or example similar to the above code to ignore the CERT errors. I also cannot find the Cookie Container for the ClientBase either. Do I need to skip using the generated code from SvcUtil.exe and switch to the HttpClient instead of the ClientBase. Or are there similar ways to store the generated cookie and ignore the CERT errors. We don't control the API we are calling and there is no REST version of the API and none coming soon so we are stuck working with what we have.
Any advice would be greatly appreciated and also thank you ahead of time
UPDATE
So i did some more research and digging and i have found that using the following code:
//Right Here we are creating the Service Object
XIEserviceClient _xieServiceRef = null;
_xieServiceRef = new XIEserviceClient();
_xieServiceRef.ChannelFactory.Credentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.None,
RevocationMode = X509RevocationMode.NoCheck
};
_xieServiceRef.ChannelFactory.Credentials.UserName.UserName = CalderaConfiguration.SelectedOS4000ApiConnection.Username;
_xieServiceRef.ChannelFactory.Credentials.UserName.UserName = CalderaConfiguration.SelectedOS4000ApiConnection.Password;
We are now able to bypass the cert errors.
Now I'm just trying to I'm to figure out the whole cookie/authentication error, I now get the following Exception:
"The content type text/html of the response message does not match the content type of the binding (text/xml; charset=utf-8)
This i believe, according to Fiddler, appears to be an authentication issue because it appears that a login page is being returned from the service i believe this is the cookie issue I'm still looking into....
There are a few things to consider :
Do you have DNS and line-of-sight to the server?
Are you using the correct name from the certificate?
Is the certificate still valid?
Is a badly configured load balancer messing things up?
Does the new server machine have the clock set correctly (i.e. so that the UTC time is correct [ignore local time, it is largely irrelevent]) - this certainly matters for WCF, so may impact regular SOAP?
Is there a certificate trust chain issue? if you browse from the server to the soap service, can you get SSL?
Related to the above - has the certificate been installed to the correct location? (you may need a copy in Trusted Root Certification Authorities)
is the server's machine-level proxy set correctly? (which different to the user's proxy);see proxycfg for XP / 2003 (not sure about Vista etc)

How to properly establish SSL connection from UWP App to WebAPI using HttpClient class?

I have an UWP application which communicates with server WebAPI. To do this I am using HttpClient class from Windows.Web.Http namespace. It does work fine if I use simple Http URL. Because of sending passwords and other sesitive data I would like to use SSL. But the problem appears when I am trying to use Https URL. Program still shows me an error which says that "The certificate authority is invalid or incorrect". I am new in certificates etc. so it does not tell me anything useful.
On some websites I found some semi-solution. Using HttpBaseProtocolFilter class I can set options to ignore some server certificate errors like this:
HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
HttpClient client = new HttpClient(filter);
It works, but only on desktop. When I run my application on Mobile Emulator, the error shows up again. Also I do not really think that this is a good solution so I have searched for something else and just found this: https://pfelix.wordpress.com/2012/12/16/using-httpclient-with-ssltls/ . There are some informations about HttpClient and SSL, but as far as I understand it is about HttpClient from namespace System.Net.Http. I tried this solution for Windows Store App, but it have not worked too.
var client = new HttpClient(new HttpClientHandler
{
ClientCertificateOptions = ClientCertificateOption.Automatic
});
So here is my question: how can I set up this HttpClient (from Windows.Web.Http or System.Net.Http) to perform working SSL connection with my WebAPI? Maybe is there something to set by server side?
Edit: I am using IIS Express from Visual Studio 2015 because I do not really know how to add my WebAPI to full IIS and let it work. I also turn on SSL in WebAPI project Properties, which generated for me a Https URL (so I thought that it would also generate a properly certificate). If I try to navigate to the Http URL everything is fine on my Mozilla Firefox and IE. The error about untrusted certificate shows when I try my https://localhost:44301/ URL in both browsers.
You were close with the HttpClientHandler approach, but you want to trust the server certificate, not the client certificate (which doesn't exist in your example). Try this:
HttpClient client = new HttpClient(new HttpClientHandler {
ServerCertificateCustomValidationCallback = (a, b, c, d) => true });
This will cause ALL server certificates to be trusted so don't use it in production, but works great for accessing an https service on localhost from a UWP app during development.

WCF Unsecured response in .NET 4.5

I'm working on client application to utilize SOAP web service. Added SOAP web services as Service reference. It connects to IBM server and server requires WS-Security basic authentification.
Called with default settings and got an error(no authentication header)
Modified code to look like so:
var service = new RealTimeOnlineClient();
service.ClientCredentials.UserName.UserName = "xxxxx";
service.ClientCredentials.UserName.Password = "yyyyy";
Now when I look at response in Fiddler - works properly (I get expected envelope from server), I get proper envelope back.
However, I get exception from WCF:
Security processor was unable to find a security header in the message. This might be because the message is an unsecured fault or because there is a binding mismatch between the communicating parties. This can occur if the service is configured for security and the client is not using security.
Quick search and bunch of answers here on SO points me to HotFix from Microsoft where they added new property EnableUnsecuredResponse. Problem is - I can't figure out WHERE to apply this property in my code OR in config. Adding to security tag in web.config doesn't work (errors out can't find property).
I understand hotfix came out for .NET 3.5 and most questions from 2009-2010. It should be in 4.5 already, correct? How do I apply this property to my code?
I had to add following code to alter value of "EnableUnsecureResponse"
var service = new RealTimeOnlineClient();
service.ClientCredentials.UserName.UserName = "xxxxx";
service.ClientCredentials.UserName.Password = "yyyyy";
var elements = service.Endpoint.Binding.CreateBindingElements();
elements.Find<SecurityBindingElement>().EnableUnsecuredResponse = true;
service.Endpoint.Binding = new CustomBinding(elements);

Using WCF service in MonoTouch with Authentication

I am using a WCF service client generated by slsvcutil form Silverlight toolkit version 4. I've also tried version 3 with the same problems. When I use a client instance running on http with no user credentials it runs without problems. But I need to switch to https for productive servers and send user credentials that are hardcoded for my application. I use the following code for that:
var binding = new BasicHttpBinding (BasicHttpSecurityMode.TransportCredentialOnly);
var endpoint = new EndpointAddress (AppSettings.FlareEndPoint);
_service = new TopicAnalystAPIClient(binding, endpoint);
_service.ClientCredentials.UserName.UserName = "xxx";
_service.ClientCredentials.UserName.Password = "xxx";
When I call a method on that service pointing to http with no authentication it works. When I use the this code against http/https with the credential I get "There was an error on processing web request: Status code 401(Unauthorized): Unauthorized" exception. I've checked that the credentials are correct, I am able to open the service reference in my browser. I've also tried several combinations of http/https and SecurityMode value. I've also tried it on four different servers always with the same result.
What can be the problem?
A lot of permutations are possible. BasicHttpSecurityMode.TransportCredentialOnly should be usable without SSL [1] using HTTP itself. This means the server will send one (or more) authentication method(s) to the client (e.g. basic, digest, ntlm) and Mono (including MonoTouch) should be providing support for the most of them.
It is possible that the linker (if used) removes one of them. In that case you could try building and testing without linking (or skip linking of System.Net.dll).
It's also possible that the authentication method that the serve insist on is not supported. You could find which one is used by running a network trace (e.g. wireshark) or, maybe, it will show up in more details in the server log (along with the 401 error).
[1] http://msdn.microsoft.com/en-us/library/system.servicemodel.basichttpsecuritymode%28v=vs.95%29.aspx

Categories