Test WCF with Mutual Certificate Authentication using SOAPUI - wcf

I´m trying to test a WCF service with mutual certificates authentication using a client on C# and it works; now I want to test the service using SOAP UI.
This is the service configuration:
<system.serviceModel>
<services>
<service behaviorConfiguration="ServiceBehavior" name="WS_XXXXX.WcfXXXX">
<endpoint address=""
binding="customBinding" bindingConfiguration="XXXSoap" bindingNamespace=""
contract="IXXXSoap" >
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:47037/"/>
</baseAddresses>
</host>
</service>
</services>
<bindings>
<customBinding>
<binding name="XXXSoap">
<security authenticationMode="SecureConversation"
requireSignatureConfirmation="false"
canRenewSecurityContextToken="true"
messageProtectionOrder="SignBeforeEncrypt"
messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11"
requireDerivedKeys="false" >
<secureConversationBootstrap
authenticationMode="MutualCertificate"
requireSignatureConfirmation="true"
canRenewSecurityContextToken="true"
messageProtectionOrder="SignBeforeEncrypt"
messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11"
requireDerivedKeys="false">
</secureConversationBootstrap>
</security>
<textMessageEncoding messageVersion ="Soap11WSAddressingAugust2004" >
</textMessageEncoding>
<httpTransport />
</binding>
</customBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior" >
<serviceCredentials>
<serviceCertificate findValue="WCfClient"
storeLocation="CurrentUser"
storeName="My"
x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
I read some info on how to test a WCF service with service certificate on SOAPUI; but because of the WCF configuration (mutual certificates), I don´t know how to configure the SOAP UI for test the WCF web service.
Thanks in advance.

When we use mutual certificate mode to authenticate the client and protect the server communication. We need to establish the trust relationship between the client and the server, then we provide the client certificate on the clients-side when calling the service. For some kinds of WCF created with message security, we might need to on the client-side provide the service certificate that the server-side used.
Anyhow, we at least a client certificate on the client-side. In SOAPUI, we are able to configure the client certificate for one request or all request.
Here are steps details.
1. Export your certificate that your client needs to provide by using the export wizard.
2. Please tick “export the private key” option.
3. Input your password.
4. Set up the certificate for all request. the menu locates in the main toolbar File > Preferences.
Result.
For sending https request for one, please refer to the below link. It is similar to these steps.
https://www.soapui.org/docs/functional-testing/sending-https-requests.html
Feel free to let me know if the problem still exists.

Related

WCF Self hosted REST server (https) keeps asking for client authentication

I created a self hosted WCF REST server (w/o IIS). When I enable SSL support, I am keep asked for a Client Certification when I test the site in Chrome.
Below is my app.config of which I believe I disabled the client authentication. Is there anything that I am missing here?
photo :
Chrome asking for client certificate
App.config code :
<system.serviceModel>
<services>
<service behaviorConfiguration="ADConnectorLibrary.Service1Behavior" name="ADConnectorLibrary.ADConnectorLibrary">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttpTransportSecurity" behaviorConfiguration="web" contract="ADConnectorLibrary.IADConnectorLibrary" >
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="https://ADDRESS:8888/ADConnectorLibrary/"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ADConnectorLibrary.Service1Behavior">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
**<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="None" />
</clientCertificate>
</serviceCredentials>**
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="webHttpTransportSecurity">
<security mode="Transport">
**<transport clientCredentialType="None" />**
</security>
</binding>
</webHttpBinding>
</bindings>
The only thing you need to do is disable the SSL setting when hosting the service in IIS.
On my side, I create a console application to host the service and bind the sslcert to the specified port with the following command. when the client calls it via browser, it does not pop up a dialog box and prompted me to select the client certificate.
netsh http add sslcert ipport=0.0.0.0:8000
certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6
appid={00112233-4455-6677-8899-AABBCCDDEEFF}
Maybe we don't need to open the support client certificate,or disable it.
clientcertnegotiation=disable
Here is the official document, wish it is useful to you.
https://learn.microsoft.com/en-us/windows/desktop/http/add-sslcert
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-configure-a-port-with-an-ssl-certificate
Feel free to let me know if there is anything I can help with.
Since you are using TransportSecurity, I believe you need to assign a certificate to your service otherwise it will not be able to encrypt the message via SSL over HTTPS.
Likewise the client would have to trust that certificate, or will get one of these reponses when the client tries to access the service via HTTPS in a brower, and calls from code will fail.
You probably need to use netsh, since you are not using IIS. You might need to reseach netsh a bit to fit your needs.
Something like this to register the cert to the port and map to the application guid: This is a pure made up example: netsh http add sslcert ipport=127.0.0.1:8000 certhash=c20ed305ea705cc4e36b317af6ce35dc03cfb83d appid={c9670020-5288-47ea-70b3-5a13da258012} clientcertnegotiation=enable
you probably don't need this since you are not apply a certificate:
**<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="None" />
</clientCertificate>
</serviceCredentials>**

WCF Server Configuration for Windows Authentication for wsHttpBinding

I have to implement "Windows Authentication" on a service hosted on Server.
I am using "wsHttpBinding". In it "Message" is the default security mode.
Below are my server configuration:
web.config
<authentication mode="Windows" />
<services>
<service name="WCFWsHttpBindingHttps.Service1" behaviorConfiguration="WCFWsHttpBindingHttps.Service1Behavior">
<!-- Service Endpoints -->
<endpoint address="" binding="wsHttpBinding" contract="WCFWsHttpBindingHttps.IService1">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFWsHttpBindingHttps.Service1Behavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
Below is my IIS configuration:
Inspite of all the configuration I am unable to access my service.
can anyone notify where I am making mistake or have I missed any configuration.
I am receiving below error when I am trying to access my service.
When you are using wsHttpBinding, the security mode must be Transport for Windows Authentication on IIS to be used, in the other side consumers needs to have a server certificate configured.
If you use another security mode you will crossed with below exception:
Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service.
so you have to wsHttpBinding as below:
<wsHttpBinding>
<binding>
<security mode="Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</wsHttpBinding>
If you use Message security mode, it means that you will be sending an encrypted message over a non-secure transport and to encrypt the message you will have to use your own a certificate, in the other side you also have to configure how the client validates the certificate, this ensure the consumers are negotiating to the right service.

Custom UserName/Password authentication in IIS6

I have a WCF service I'm hosting in IIS6. I'm trying to set up custom username/password authentication using Transport level security. I've set up a test certificate and got a client to connect over SSL with no authentication specified, i.e:
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
I've set up a custom validator with Message security and client credential type "UserName", but I'd like to incorporate this now with Transport level security. When I have my web.config set, when I try to view the WSDL, I get an error:
"Security settings for this service require 'Basic' Authentication but it is not enabled for the IIS application that hosts this service."
Here are the important parts of my web.config:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="UserNameBinding">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="ServiceAuthenticationBehavior"
name="Service.WebServices.MyService">
<endpoint address="mex" binding="mexHttpsBinding" bindingConfiguration=""
name="mexBinding" contract="IMetadataExchange" />
<endpoint binding="wsHttpBinding" bindingConfiguration="UserNameBinding"
name="wsHttpBindingWithAuth" contract="Service.WebServices.IMyService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceAuthenticationBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate findValue="TestCert01" storeLocation="LocalMachine"
storeName="TrustedPeople" x509FindType="FindBySubjectName" />
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="Service.WebServices.ClientCredentialsValidator, Service.WebServices" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
Is there something I'm supposed to set in IIS6 to enable this?
In IIS, I started initially with the "Enable anonymous access" option enabled. I also tried enabling "Basic authentication (password is sent in clear text)" checkbox, but no success.
This post seems to suggest that Basic is only available for Windows account, with a 3rd party solution...
Basic Authentication with WCF REST service to something other than windows accounts?
I've been here myself, and ended up going with 1-legged openauth which worked nicely.
edit
this post sent me well on my way to a solution http://www.cleancode.co.nz/blog/523/oauth-dot-net
its worth mentioning the diff between 1 and 2-leg OAuth. 1-leg is where the client and the service both know the client's secret (password) for the client's account name which is used to encrypt and decrypt the authentication request (which all gets added to the querystring). with 2-legged, this is generated by a 3rd party such as google, facebook etc.

Using client certificates for authentication

The client machine has the "TicketSalesClient" certificate in "My" storage of current user and the "TicketSalesServer" certificate in "TrustedPeople" storage of current user. The server machine has "TicketSalesClient" certificate in "TrustedPeople" storage of local machine and the "TicketSalesServer" certificate in "My" storage of local machine.
The service runs under IIS 7. Below is the web.config file:
<system.serviceModel>
<services>
<service behaviorConfiguration="secureBehavior" name="InternetRailwayTicketSales.TicketSalesImplementations.TicketSalesService">
<endpoint address="TicketSalesService"
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding" contract="InternetRailwayTicketSales.TicketSalesInterface.ITicketSales" />
<endpoint address="TicketSalesServiceSecureMex"
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://localhost:443/TicketSales/" />
</baseAddresses>
</host>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="secureBehavior">
<serviceThrottling maxConcurrentInstances="5000" maxConcurrentSessions="5000" />
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="True" />
<serviceCredentials>
<serviceCertificate findValue="TicketSalesServer"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName"/>
<clientCertificate>
<authentication certificateValidationMode="PeerTrust"/>
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
The service in IIS is configured for SSL and certificate requiring.
1)Now when I try to add service reference in the client I receieve: "The HTTP request was forbidden with client authentication scheme 'Anonymous'. The remote server returned an error: (403) Forbidden."
2)If I try to request the metadata endpoint using browser I firstly apply the SSL certificate and then receieve an error that "The credentials do not give the right to view this directory or page." As I understand this is because I can't give the client credentials through the browser.
3)I tried to use svcutil with configuration file which contains client credentials:
<configuration>
<system.serviceModel>
<client>
<endpoint
behaviorConfiguration="ClientCertificateBehavior"
binding="basicHttpBinding"
bindingConfiguration="Binding1"
contract="IMetadataExchange"
name="https" />
</client>
<bindings>
<basicHttpBinding>
<binding name="Binding1">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="ClientCertificateBehavior">
<clientCredentials>
<clientCertificate findValue="TicketSalesClient"
storeLocation="CurrentUser"
storeName="My"
x509FindType="FindBySubjectName" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
And then:
svcutil https://veryLongAddress.svc?wsdl /config:svcutilConf.config
And the response is that the "The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. The remote certificate is invalid according to the validation procedure"
So what am I doing wrong?
Seems like your certificates installation is fine. Can you try as shown below and see the output. Try to browse to the service from IE and you should be able to see the service and its wsdl.
Go to IE and then
Tools --> Internet Options --> Security --> Internet --> Custom Level
Tools --> Internet Options --> Security --> Intranet --> Custom Level
Now scroll down to Misc section to find the option "Dont Prompt for client certificate selection when no certificate is present or only one certificate is present" to Diable.
Now restart IE and browse to the service and IE should ask you to select a client certificate from the personal store and you need to select mvc.localhost.
If TicketSalesClient cert is not visible then your client certificate is not in the appropriate store.
The reason for this is that the file you are using to install the certificates do matter as well as the purpose for which the certificate has been created. You can find the purpose of each certificate when you double click them in the certificate store you have a column that is called Intended Purpose. Make sure its for your client certificate.
When hosting the service in IIS all endpoints must have the same transport security configuration. I played with this before and I ended with redefining binding for WSDL GET (yes it has also internal binding defined). So modify your bindings on service to:
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpBinding>
<customBinding>
<binding name="wsdlBinding">
<textMessageEncoding messageVersion="None" />
<httpsTransport requireClientCertificate="true" />
</binding>
</customBinding>
And in service behaviors use:
<serviceMetadata httpsGetEnabled="true"
httpsGetBinding="customBinding"
httpsGetBindingConfiguration="wsdlBinding" />
This should force WSDL get to require client certificate and it "should" work from browser (unless there is some other problem).
When we host WCF service in IIS with security type transport and client credential type certificate, Then put your client certificate on Root store and enable anonymous authentication in IIS. Enable anonymous authentication in IIS But most important, add your certificate to root store.

netTcpBinding without Windows credentials?

I've got a machine-control application where I have a single client computer and five server boxes communicating on the machine subnet. There is no domain controller. I would like to use netTcpBinding to allow for reliability and transaction support.
Is is possible to use username / password authentication with this binding, when a domain controller is not present? I would prefer not to use a certificate as I don't want to manage certificates across 900 computers (150 machines) that will not be connected to the office LAN.
Yes, of course - but only if you use Message security (rather than transport security). Define your binding configuration like so:
<netTcpBinding>
<binding name="UserNameSecurity">
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</netTcpBinding>
and then reference that binding configuration in your endpoints (on server and client):
<endpoint address="....."
binding="netTcpBinding"
bindingConfiguration="UserNameSecurity"
contract="IMyService" />
Marc
UPDATE:
Ah, yes, on the server-side, you'll need a certificate to authenicate the service to the client calling it, and it's also used to encrypt+sign the messages. That's on the server only - clients need not install anything.
Configuration:
<behaviors>
<serviceBehavior>
<behavior name="ServerInternet">
<serviceCredentials>
<serviceCertificate
findValue="MyServiceCertificate"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehavior>
</behaviors>
<services>
<service name="MyServiceInternet"
behaviorConfiguration="ServerInternet">
....
</service>
</services>
Make sure to install your server's certificate into the "Local Machine" folder on your server, under the "subject name" that you specify in your config.
There is something you can try first. Set serviceNegotiationCredentials to true:
<message negotiateServiceCredential="true"/>
This will create a secure conversation between your client and your service without a domain controller.
BUT, if there isn't any domain controller, the client doesn't trust your service, so it will fail.
So you should set the expected identity of the service. You can find that in the WSDL of your service. By default, if you are hosted on IIS, it seems to be:
<client>
<endpoint>
<identity>
<servicePrincipalName value="host/NETWORKSERVICE"></servicePrincipalName>
</identity>
</endpoint>
</client>
I don't think you'll need it, but maybe you'll have to allow anonymous logon on the service side:
<serviceBehaviors>
<behavior>
<serviceCredentials>
<windowsAuthentication allowAnonymousLogons="true"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>