WCF client. Client Certificate. First call success, Second call fails - c#

I'm trying to connect to a soap web service over https, with soap11 and client certificate credentials using c# .NET 4.5. I use the tool of vs to add service reference and it create a soap client for me.
I have create a customBinding to accomplish https over soap11:
App.config
<system.serviceModel>
<bindings>
<customBinding>
<binding name="*****" closeTimeout="00:02:00" openTimeout="00:02:00" receiveTimeout="00:05:00" sendTimeout="00:05:00">
<textMessageEncoding messageVersion="Soap11"/>
<httpsTransport useDefaultWebProxy="false" requireClientCertificate="true" allowCookies="false" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="******************"
behaviorConfiguration="******************"
binding="customBinding" bindingConfiguration="******************"
contract="******************"
name="******************" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="******************">
<clientCredentials>
<clientCertificate findValue="******************" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
c# code:
var client = new IConsultService.ConsultServiceClient();
client.consult("1");
client.consult("1"); <!-- fail error 404 - there was not endpoint listening at
If I post without certificate in receive a tomcat 404, if I send the client certificate works ok the first time and it seems to me that I'm being redirected. The problem is that at the sencond request fail (404), also if I instantiate the client again fails. Only work again when stop the application and start it again. It seems that somethings is cached in the static stack of the program.
And since is a 404 my guess is that is something from the client certificate, if I request without the certificate the error is the same.
I tryied to create bindings programatically, set ClientBase.CacheSetting = CacheSetting.AlwaysOff without luck.
Edit1:
Using System.Net.HttpWebRequest happens the same, first request ok, second request 404.
Edit2:
It seems that there is something on the handshake first request send "Certificate, Client Key Exchange" and second request "Change cipher Key Exchange"
is there a way to force to close the channel and always send"certificate, client key exchange"?
Thanks

First, if we authenticate the client with X509certificate, we commonly need to establish the trust relationship between the server and the client, namely, we should install each other’s certificate in the trusted root certificate authority, and the client needs to provide an Identity to confirm the identity of the server (this is usually the public key of the server's certificate, or the host name)
<endpoint address="net.tcp://10.157.13.69:4386/" binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_ITestService" contract="ServiceReference1.ITestService"
name="NetTcpBinding_ITestService">
<identity>
<dns value="vabqia969VM" />
</identity>
</endpoint>
Second, I suspect the issue is caused by the TLS version. Have you tried to upgrade the Dotnetframework of these project? at least 4.6.2 above. Please refer to the following document.
https://learn.microsoft.com/en-us/dotnet/framework/network-programming/tls
Feel free to let me know if the problem still exists.

Related

Communicate Azure App Service to locally hosted IIS WCF Service [duplicate]

I'm building an ASP.NET website - it's a solution with a few projects, a data base and a web service. Everything worked fine, but last time I tried to run the project, I got the following error:
There was no endpoint listening at http://localhost:[number]/BooksWS.svc that could accept the
message. This is often caused by an incorrect address or SOAP action. See InnerException,
if present, for more details.
The inner exception says:
Unable to connect to the remote server
This error sort of came out of the blue, so I'm not sure what additional information I should provide. Does anyone have any idea why this could happen?
I suppose even a general answer could help, the only info I found about this error in the web concerned WCF.
go to webconfig page of your site, look for the tag endpoint, and check the port in the address attribute, maybe there was a change in the port number
Another case I just had - when the request size is bigger than the request size set in IIS as a limit, then you can get that error too.
Check the IIS request limit and increase it if it's lower than you need.
Here is how you can check and change the IIS request limit:
Open the IIS
Click your site and/or your mapped application
Click on Feature view and click Request Filtering
Click - Edit Feature Settings.
I just found also another thread in stack
IIS 7.5 hosted WCF service throws EndpointNotFoundException with 404 only for large requests
An another possible case is make sure that you have installed WCF Activation feature.
Go to Server Manager > Features > Add Features
I had this problem when I was trying to call a WCF service hosted in a new server from a windows application from my local. I was getting same error message and at end had this "No connection could be made because the target machine actively refused it 127.0.0.1:8888". I donot know whether I am wrong or correct but I feel whenever the server was getting request from my windows application it is routing to something else. So I did some reading and added below in Web.config of service host project. After that everything worked like a magic.
<system.net>
<defaultProxy enabled="false">
</defaultProxy>
</system.net>
Short answer but did you have Skype open? This interferes specifically with ASP.NET by default (and localhosts in general) using port:80.
In Windows: Go to Tools -> Options -> Advanced -> Connection and uncheck the box "use port 80 and 443 as alternatives for incoming connections".
Try this:
Delete the service instance.
Create a new instance of the service.
Sometimes the port is changed and generated error.
I tried a bunch of these ideas to get HTTPS working, but the key for me was adding the protocol mapping. Here's what my server config file looks like, this works for both HTTP and HTTPS client connections:
<system.serviceModel>
<protocolMapping>
<add scheme="https" binding="wsHttpBinding" bindingConfiguration="TransportSecurityBinding" />
</protocolMapping>
<services>
<service name="FeatureService" behaviorConfiguration="HttpsBehavior">
<endpoint address="soap" binding="wsHttpBinding" contract="MyServices.IFeature" bindingConfiguration="TransportSecurityBinding" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="HttpsBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="TransportSecurityBinding" maxReceivedMessageSize="2147483647">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
If you are using custom binding, please make sure that you are putting the same name for both custom binding (Server and Client)in config files
<bindings>
<customBinding>
<binding name="BufferedHttpServerNoAuth" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00">
<gzipMessageEncoding innerMessageEncoding="textMessageEncoding" MaxArrayLength="10485760" MaxBytesPerRead="31457280" MaxStringContentLength="102400000" />
<httpsTransport hostNameComparisonMode="StrongWildcard" manualAddressing="False" maxReceivedMessageSize="31457280" authenticationScheme="Anonymous" bypassProxyOnLocal="True" realm="" useDefaultWebProxy="False" />
</binding>
</customBinding>
</bindings>
the binding name "BufferedHttpServerNoAuth" should be same in both.
Hope this would help someone
This is ancient history but I just ran into this issue and the fix for me was recycling the application pool of the website in IIS. Easy fix, for once.
I changed my website and app bindings to a new port and it worked for me. This error might occur because the port the website uses is not available. Hence sometimes the problem is solved by simply restarting the machine
-Edit-
Alternative (and easier) solution:reference
Get PID of process which is using the port
CMD command-
netstat -aon | findstr 0.0:80
Use the PID to get process name -
tasklist /FI "PID eq "
Open task manager, find this process and stop it.
(Note- Make sure you do not stop Net.tcp services)
I solved it by passing the binding with endpoint.
"http://abcd.net/SampleFileService.svc/basicHttpWSSecurity"
Click on Service which you have created right click on it then select update references after this rebuild the application it will work

How do I setup SSL over WCF?

The error I'm receiving in production environment:
The remote certificate is invalid according to the validation procedure.
[AuthenticationException: The remote certificate is invalid according to the validation procedure.]
System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, Exception exception) +2755308
System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) +470
The production environment is using a three tier architecture, Web talks to App and App talks to database. Web and App use WCF service layer to communicate over SSL (443). We believe it might be configuration in either SSL certificate in IIS7 or a WCF configuration issue.
What we tried:
I added the certificate in in both App and Web to the Trusted Authority for both "Local Computer" and "Current User".
I can add my WCF Web Config if need be.
I tried the following recommendations:
https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.storename(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/ms734695.aspx
"The remote certificate is invalid according to the validation procedure." using Gmail SMTP server
How do I know what the storeName of a certificate?
https://msdn.microsoft.com/en-us/library/ms733813(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/hh556232%28v=vs.110%29.aspx
Self-Hosted WCF Service with Mutual SSL (between Service and Client) fails with 403 Forbidden
This answer is for Client certificates where you are sending a Certificate with your payload to an HTTPS end point.
You'll want to make sure that you trust the certificate, that you trust the certificate authority that created it, and that you have that CA's certificate in your trusted store.
Are you able to go to a simple webpage on your system (not WCF service) where you need to provide the certificate?
ie: https://mysite/test.aspx
This will allow you to test certificates outside of WCF and let you separate WCF issues from IIS issues.
1) Make sure you've setup Certificate mapping in IIS.
http://www.iis.net/configreference/system.webserver/security/authentication/clientcertificatemappingauthentication
http://blogs.msdn.com/b/asiatech/archive/2014/02/13/how-to-configure-iis-client-certificate-mapping-authentication-for-iis7.aspx
Short tl;dr; for what we do:
Add your client cert to your cert store (private key)
Add a user to the local users
go to IIS and map the certificate to the user you create
run winhttpcfg.exe to give your App Pool's user
access to that certificate
https://msdn.microsoft.com/en-us/library/windows/desktop/aa384088%28v=vs.85%29.aspx
2) Make sure your web.config is setup properly
(sample from ours that allow the end point to be hit via HTTP and HTTPS)
<bindings>
<basicHttpBinding>
<!-- Secure Bindings -->
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
<binding name="httpBinding">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<!-- Person Revised Service-->
<service name="Services.PRPA_AR101202" behaviorConfiguration="ServiceBehaviour">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="secureHttpBinding" contract="Services.IPRPA_AR101202"></endpoint>
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="httpBinding" contract="Services.IPRPA_AR101202" />
</service>
</services>
Again, this answer is for client certificates with messages, if it's just regular HTTP you can ignore it

securing .svc webservice with a x509 certificate [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have a .svc web service hosted on my server we are using behavior low as a test to make sure that the webservice caller get what they are supposed to get.
now I want to use x509 certificate, I have the certificate and need to send it to the consumer so that they can double check if it is possible to exchange data.
I am not sure which steps to follow
I have these two documentation but I want to double check with anyone who knows how this can be done better.
steps to enable x509
Pattern and practice WCF
If you want to use x509 certificate to authenticate clients that call your WCF service, then the first article you referenced is a pretty good step-by-step guide.
http://www.codeproject.com/Articles/36683/simple-steps-to-enable-X-certificates-on-WCF
This article assumes that both your client and service run on the same machine, so you will need to adjust instructions for your specific case.
Step 1: Create client and server certificates
Since you already have the certificates, you may skip this step. You would have to replace WcfServer and WcfClient with the names from your server and client certificates in steps 3 and 7.
Step 2: Copy the certificates in trusted people certificates
The referenced article explains how to open Certificates snap-in in MMC. Since you are using your existing certificates, you may need to import your service certificate on the server and client certificate on the client machine. Then export client certificate without private key and import it into Trusted People folder on the server machine.
Step 3: Specify the certificate in the WCF service web.config file
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerTrust"/>
</clientCertificate>
<serviceCertificate findValue="!Insert name from your server certificate here!"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
Step 4: Define binding in the WCF service web.config file
<bindings>
<wsHttpBinding name="wsHttpEndpointBinding">
<binding>
<security>
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
Step 5: Tie up the bindings with the end point in the WCF service web.config file
<endpoint address="" binding="wsHttpBinding"
bindingConfiguration="wsHttpEndpointBinding" contract="WCFServiceCertificate.IService1">
Step 6: Make your web application client for consuming the WCF service.
When you add a service reference, Visual Studio inserts element in the client web.config file. You will need to modify it as in steps 7 and 8.
Step 7: Define certificate for WCF client in the client web.config file
<behaviors>
<endpointBehaviors>
<behavior name="CustomBehavior">
<clientCredentials>
<clientCertificate findValue="!Insert name from your client certificate here!"
x509FindType="FindBySubjectName"
storeLocation="CurrentUser" storeName="My" />
<serviceCertificate>
<authentication certificateValidationMode="PeerTrust"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
Step 8: Tie up the behavior with the end point on WCF client in the client web.config file
You would need to replace address, contract and dns value to match your actual WCF service.
<client>
<endpoint address="http://localhost:1387/Service1.svc" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IService1" contract="ServiceReference1.IService1"
name="WSHttpBinding_IService1" behaviorConfiguration="CustomBehavior">
<identity>
<dns value="WcfServer" />
</identity>
</endpoint>
</client>

IIS 7.0 Web Service - Works on HTTP (80), Fails with error 404 on HTTPS (443)

IIS 7.0 on Windows 2008
WCF Web Service, .NET 4 from VS 2010
Web service is installed via publishing and I have full admin rights on the server. There are several complicated methods, but there is a simple one that returns the build version. If we can get this one working, I can fix them all - here is my interface:
namespace MyNameSpace
{
[ServiceContract]
public interface WebInterface
{
[OperationContract]
[WebGet]
string GetVersion();
Attempt to connect via HTTP:// and everything works fine!
Attempt to conenct via HTTPS:// I get a 404 file not found.
I can reach the generic "You have created a web service..." page, including full web service path and the C# generic sample code when browsing to the exact same URL's both on HTTP and HTTPS.
In C#, I have read that the certificate can cause trouble, and I have already implemented the delegate overload to approve our server certificate.
I suspect missing one or more entries in the Web.config file, but I don't have a clue where to start. I have tried Google searching and Stack Overflow searching, but I haven't found the correct combination of search terms to help with this particular issue.
Web Config:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="HttpGetMetadata">
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="LinkService" behaviorConfiguration="HttpGetMetadata">
<endpoint address="" contract="WebInterface" binding="basicHttpBinding" />
</service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Help Please.
You're using the defaults for basicHttpBinding, and the default security mode for that binding is None. You need to define the binding and set the security mode to Transport in your config. Add a Bindings section to your ServiceModel section, like this:
<serviceModel>
<Bindings>
<basicHttpBinding name="secureBinding">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</basicHttpBinding>
</Bindings>
</serviceModel>
Then you need to assign this binding to your endpoint via the bindingConfiguration attribute, like this:
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="secureBinding"
contract="WebInterface" />
You'll probably want to enable httpsGetEnabled as well:
<serviceMetadata httpGetEnabled="true"
httpsGetEnabled="true" />
See BasicBinding with Transport Security (which is what the sample code is based on).
You can also google with terms like "BasicHttpBinding WCF SSL" and stuff like that - lots of examples and information on the web, it's just a matter of using the right words :)
Also, I'm not 100% confident that the transportClientCredential setting is correct for your scenario (it might need to be Certificate), but I've done very little with SSL for WCF.
There may be other issues as well (like how IIS is set up on your machine), but the above is what's needed for the config.

How to sign a SOAP request with WCF

I have an 3rd party SOAP web service. I need to make a call to one of its methods. The request needs to be signed. How can I sign the request?
I assume by signing you mean that you sign the message using a certificate that is installed on the client side.
Doing this is relatively easy in WCF. Assuming you are using the wsHttpBinding in the security element you have to set the mode to SecurityMode.Message. You also have to set the clientCredentialType of the message element to MessageCredentialType.Certificate.
Then, you would have to set up a endpoint behavior and configure the clientCertificate element (which is a child of the clientCredentials element) to indicate where the client certificate is stored.
Even if you aren't using the wsHttpBinding, the configuration is pretty much the same for most of the other bindings when you want to use a client certificate to provide message-level security.
If you are making the call over HTTPS, then note that you will have to set the mode attribute on the security element to Mode.TransportWithMessageCredential.
The following is a question that was asked about using WCF to use the Amazon SOAP service which requires signing. I think the answer gives a great example, which might help with your situation.
How to sign an Amazon web service request in .NET with SOAP and without WSE
Edit: There was evidently some confusion about the link to this other StackOverflow question. I would like to point out the highest voted chosen answer. It is most definitely a WCF solution. You will notice the class SigningMessageInspector which inherits from IClientMessageInspector (a WCF interface). I think this section might help you.
Building on the very helpful answer from #casperOne I ended up with the following config:
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding>
<security mode="TransportWithMessageCredential">
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<!-- specifies the endpoint to use when calling the service -->
<endpoint address="https://SomeEndPointUrl/v1"
binding="wsHttpBinding"
behaviorConfiguration="SigningCallback"
contract="ServiceReference1.EboxMessagePortType" name="MyBindingConfig">
</endpoint>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="SigningCallback">
<clientCredentials>
<clientCertificate findValue="*somecertsubjectname*"
storeLocation="LocalMachine"
storeName="TrustedPublisher"
x509FindType="FindBySubjectName"
/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
This for a soap client over https

Categories