Securing WCF with basichttpbinding - wcf

I am using basicHttpBinding,message security and x509 certificate in my WCF service(.Net Framework 4.0).The config looks like this:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<serviceCertificate findValue="MyWebSite" storeLocation="LocalMachine"
storeName="My" x509FindType="FindBySubjectName" />
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="CToSave.ValidateClient, CToSave" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
<standardEndpoints>
<webScriptEndpoint>
<standardEndpoint crossDomainScriptAccessEnabled="True"/>
</webScriptEndpoint>
</standardEndpoints>
<services>
<service behaviorConfiguration="ServiceBehavior" name="CToSave.MyService">
<endpoint address="" binding="basicHttpBinding" contract="CToSave.IMyService" bindingConfiguration="BindingConfig"/>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="BindingConfig" openTimeout="00:50:00" sendTimeout="00:50:00" receiveTimeout="00:50:00" closeTimeout="00:50:00" maxReceivedMessageSize="2147483647">
<security mode="Message">
<message clientCredentialType="Certificate"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
A PHP client will be consuming this service. In order to consume it,will the client need a certificate at his end?I would prefer that the client doesnt have to generate a certificate.
If the clinet has to get a certificate,will my config change? If yes,what changes will I have to make?
I have read dozens of articles on basihttpbinding+security but none of them indicate anything about the certificate on the client-side. Please help.

Yes, client needs a certificate because of this:
<security mode="Message">
<message clientCredentialType="Certificate"/>
</security>
In general client does not generate its own certificate but gets it from agree provider (can be cert authority in the organization or a public authority or service owner).
In any case you need a good WS-Security library for PHP since you need to generate the message format WCF expects (this is message level security).

Actually it is possible to validate certificate by identity on a client

Related

request for a specific client certificate in nettcp bindings

Is it possible to configure net tcp binding
to request a specific certificate to be supplied by the client ?
not just certificate which is trusted by the server but the exact same certificate defined in the server ?
Thanks
You use netTcpBinding and need a specific certificate to verify, you can view my demo.
This is the app.config in service:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="Microsoft.Samples.X509CertificateValidator.CalculatorService" behaviorConfiguration="CalculatorServiceBehavior">
<!-- use host/baseAddresses to configure base address provided by host -->
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8040/servicemodelsamples/service"/>
</baseAddresses>
</host>
<!-- use base address specified above, provide one endpoint -->
<endpoint address="certificate" binding="netTcpBinding" bindingConfiguration="Binding" contract="Microsoft.Samples.X509CertificateValidator.ICalculator"/>
</service>
</services>
<bindings>
<netTcpBinding>
<!-- X509 certificate binding -->
<binding name="Binding">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</netTcpBinding>
</bindings>
In the behavior node, we can specify the information of the certificate to be used.
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="Custom" customCertificateValidatorType="Microsoft.Samples.X509CertificateValidator.CustomX509CertificateValidator, service"/>
</clientCertificate>
<serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
This is the app.config in client:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<client>
<!-- X509 certificate based endpoint -->
<endpoint name="Certificate" address="net.tcp://localhost:8040/servicemodelsamples/service/certificate" binding="netTcpBinding" bindingConfiguration="Binding" behaviorConfiguration="ClientCertificateBehavior" contract="Microsoft.Samples.X509CertificateValidator.ICalculator">
</endpoint>
</client>
<bindings>
<netTcpBinding>
<!-- X509 certificate binding -->
<binding name="Binding">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="ClientCertificateBehavior">
<clientCredentials>
<serviceCertificate>
<authentication certificateValidationMode="PeerOrChainTrust"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
In client.cs, we need to specify the certificate to be used through the setcertificate method.
client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "alice");

WCF error The client certificate is not provided. Specify a client certificate in ClientCredentials

I am trying to call a WCF service .I created a selfsigned certificate and installed in my localmachine \personnal \certificates , and also I added that in my section .But I don't understand why this error is .
Here is my web.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttpEndpoint">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://abcdxyz.abc.syntax.com/TestCCService.svc"
binding="wsHttpBinding" bindingConfiguration="wsHttpEndpoint"
contract="TestCCService.ITestCCService" name="wsHttpEndpoint" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="CustomBehavior">
<clientCredentials>
<clientCertificate findValue="abc.mymachine.name.com" x509FindType="FindBySubjectName"
storeLocation="LocalMachine" storeName="My" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
but when I try to call my service method its throwing errors
"The client certificate is not provided. Specify a client certificate in ClientCredentials."
Appreciate your suggestions to resolve this error ?
I forgot to include behaviorConfiguration="CustomBehavior"
<endpoint address="https://abcdxyz.abc.syntax.com/TestCCService.svc"
binding="wsHttpBinding" bindingConfiguration="wsHttpEndpoint"
contract="TestCCService.ITestCCService" name="wsHttpEndpoint" **behaviorConfiguration="CustomBehavior"** />
and its working now .
Thank you for help

Simplified Configuration wsHttpBinding

I'm having a simple WCF service, deployed to IIS. I used simplified configuration with BasicHttpBinding, which worked fine.
Now I wanted to add Username/Password authentication and used wsHttpBinding. In the document above it is stated:
In .NET Framework 4, the element is optional. When a service
does not define any endpoints, an endpoint for each base address and
contract implemented are added to the service. The base address is
appended to the contract name to determine the endpoint and the
binding is determined by the address scheme.
What does this mean, how am I supposed to configure the wsHttpBinding binding by address scheme?
My config looks like this:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding>
<security mode="Message">
<transport clientCredentialType="None"/>
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="SampleWebservice.CustomValidator,SampleWebservice" />
</serviceCredentials>
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
This is Windows Server 2008, IIS 7.
It seems, the service is not picking up the wsBinding settings, as I can always see a BasicHttpBinding in the downloaded svc-file. Am I missing something?
EDIT
I applied the changes suggested by user stevedocious to alter my web.config file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="SampleWebservice.SampleWebservice.Sample" behaviorConfiguration="customServiceBehaviour">
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
<endpoint contract="SampleWebservice.SampleWebservice.ISample" binding="wsHttpBinding" bindingConfiguration="bindingConfiguration" address="" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="bindingConfiguration">
<security mode="Message">
<transport clientCredentialType="None"/>
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="customServiceBehaviour">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="SampleWebservice.CustomValidator,SampleWebservice" />
</serviceCredentials>
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
However, the metadata can't be exposed. Checking the service with the browser states, that my metadata publishing is currently disabled.
You will need to create an endpoint if you want to use anything other than the basicHttpBinding with the http/https address scheme.
In your binding definition add a name attribute
< binding name="myWSBinding" ... >
then add a bindingConfiguration and binding parameter to your endpoint definition
< endpoint binding="wsHttpBinding" bindingCongifuration="myWSBinding" ... >

Pass ClientCredentials.UserName to server

Web config:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceCredentialsBehavior">
<serviceCredentials>
<serviceCertificate findValue="cool" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
</serviceCredentials>
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="ServiceCredentialsBehavior" name="Service">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="MessageAndUserName" name="SecuredByTransportEndpoint" contract="IService"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="MessageAndUserName">
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<client/>
</system.serviceModel>
<system.web>
<compilation debug="true"/>
</system.web>
Client cfg:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService" >
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:48097/WCFServer/Service.svc"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IService"
contract="ServiceReference1.IService"
name="WSHttpBinding_IService">
<identity>
<dns value ="cool" />
</identity>
</endpoint>
</client>
</system.serviceModel>
The scope is to pass ClientCredentials.UserName.UserName/Password through a secure connection.
I did x509 certificates with pluralsight self cert..
The error is:
SOAP security negotiation with 'http://localhost:48097/WCFServer/Service.svc'
for target
'http://localhost:48097/WCFServer/Service.svc'
failed. See inner exception for more
details.
InnerException:
The X.509 certificate CN=cool chain
building failed. The certificate that
was used has a trust chain that cannot
be verified. Replace the certificate
or change the
certificateValidationMode. A
certificate chain processed, but
terminated in a root certificate which
is not trusted by the trust provider.
How can i solve this exception?
Regards,
Sergiu.
You are using self signed certificate which is not trusted by default. You must tell your client application that it should trust the certificate:
<behaviors>
<endpointBehaviors>
<behavior name="LocalCertValidation">
<clientCredentials>
<serviceCertificate>
<authentication certificateValidationMode="PeerTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
Reference this behavior from your endpoint configuration in client by behaviorConfiguration="LocalCertValidation". To make it work you must install public certificate to current user's certification store under trusted people. You can also set validation mode to None and certificate will not be validated at all but that should be used only in development environment.

WCF with WSHttpBinding, Message Security, clientCredentialType="UserName" Cerificate SelfHosted Issue

I have created a Service where I need the client to pass the credentials (username and password). This behavior requires a X509 certificate, so i started for development issues with a self-signed one using makecert.exe.
Because I'm so newbie with certificates, i see that this certificate created on the IIS Server Certificates section, I need my service to be self hosted later on a windows service, for testing purposes i use a console host application and a simple winform app client.
So my question is, How do i deploy this certificate? I don't want to use IIS in anyway, I can embed the certificate where i noticed i can export as .pfx file inside the console/windows service host? And how?
I'm posting my service and client config files for help on understanding what I need.
Server Configuration:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="B2B.WCF.Service.B2BService" behaviorConfiguration="wsBehavior">
<endpoint name="WSHttpEndpointB2B"
bindingConfiguration="WSBinding"
address ="http://localhost:8768/ServB2B"
binding="wsHttpBinding"
contract="B2B.WCF.Contracts.IB2BContracts">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="wsBehavior">
<serviceMetadata httpsGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate findValue="MyServerCert" x509FindType="FindBySubjectName"
storeLocation="LocalMachine" storeName="My" />
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="B2B.WCF.Service.UserValidator, B2B.WCF.Service" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="WSBinding">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
Client Configuration:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint name="WSHttpEndpointB2B"
bindingConfiguration="WSBinding" behaviorConfiguration="wsBehavior"
address ="http://localhost:8768/ServB2B"
binding="wsHttpBinding"
contract="B2B.WCF.Contracts.IB2BContracts">
<identity>
<dns value="MyServerCert"/>
</identity>
</endpoint>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="wsBehavior">
<clientCredentials>
<clientCertificate findValue="MyServerCert" x509FindType="FindBySubjectName"
storeLocation="LocalMachine" storeName="My"/>
<serviceCertificate>
<authentication certificateValidationMode="None"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="WSBinding">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
Thanx in advance
Your certificates need to be imported into the Windows Certificate Store on the machine that is hosting your web service (i.e. "the server") and (optionally) on the machine that is using your web service (i.e. "the client", if it is a different machine).
You should use the Microsoft Management Console (MMC) to do this. First, you should set it up according to this article. Then import your certificates according to the steps in this article. Make sure you choose the correct store for the client certificate (i.e. 'Personal') and root certificate (i.e. 'Trusted Root Certification Authorities').
Your web service won't start unless it finds the correct certificates that are referenced in your configuration files. In your case, this is the "MyServerCert" certificate that you want to store in the 'Personal' store.