Client certificate is required. No certificate was found in the request - wcf

I’m trying to setup a security transport using certificates over a SSL service.
The service is installed over IIS, I have configured it using a “MyLaptop” certificate (stored on local machine/Personal) validated by a self-signed certificate (“My Root CA” certificate – stored on local machine Trusted Root Certification Authorities). Everything seems to be OK with the service; I can access it using the Internet Explorer.
On the server side the web.config looks like
<behaviors>
<serviceBehaviors>
<behavior name="EchoServiceBehavior">
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerTrust" revocationMode="NoCheck" />
</clientCertificate>
</serviceCredentials>
<serviceMetadata httpsGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="MutualSslBinding">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="EchoServiceBehavior" name="HttpsBindingDemo.EchoService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="MutualSslBinding"
contract="HttpsBindingDemo.IEchoService">
<identity>
<dns value="MyLaptop" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="https://MyLaptop:12643/EchoService/" />
</baseAddresses>
</host>
</service>
On the client side I have installed a new certificate “MyClient” (stored on CurrentUser/Personal) validated by the same “My Root CA” certificate.
On the client side the app.config looks like
<behaviors>
<endpointBehaviors>
<behavior name="EchoClientBehavior">
<clientCredentials>
<clientCertificate findValue="MyClient" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IEchoService">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://MyLaptop:12643/EchoService/EchoService.svc" behaviorConfiguration="EchoClientBehavior"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IEchoService"
contract="SecuredServices.IEchoService" name="WSHttpBinding_IEchoService">
<identity>
<dns value="MyLaptop" />
</identity>
</endpoint>
</client>
Every time when trying to execute the operations of the EchoService.svc I’m receiving the error below:
“The HTTP request was forbidden with client authentication scheme 'Anonymous'.”
Enabling the service’s log I found that first exception message is in fact “Client certificate is required. No certificate was found in the request. This might be because the client certificate could not be successfully validated by the operating system or IIS. For information on how to bypass those validations and use a custom X509CertificateValidator in WCF please see http://go.microsoft.com/fwlink/?LinkId=208540.”.
Could you please help me to understand how to correctly configure the service to avoid the described errors?
Thank you!

It looks like you are most likely missing the serviceCertificate tag inside of your serviceCredentials tag in your service behavior. Try adding this and it should resolve the issue. Each time I use certificates with a WCF service I always have to specify in the config what certificate the service should be using.
http://msdn.microsoft.com/en-us/library/ms731340%28v=vs.110%29.aspx

When you import client cert to your personal store, try to import using pfx file and specifying the password

Related

Client certificate authentication WCF

So I'm completely lost with certificates. I've searched all over the web for solutions and tutorials for this and found nothing that can really help me.
What I'm trying to do is to have both server and client certificate validation for my WCF client-server application. The application is hosted on IIS.
I want it on my dev computer (the server is localhost) and in test (where im the client and the server is a windows server).
the configuration I have now is:
Client:
<behaviors>
<endpointBehaviors>
<behavior name="myBehaviorConfig">
<clientCredentials>
<clientCertificate findValue="CN=MyTestClientCertificate"
storeLocation="LocalMachine"
x509FindType="FindBySubjectDistinguishedName"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="MyBindingConfig">
<security mode="TransportWithMessageCredential">
<transport realm=""/>
<message clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://localhost/Service.Calculator.svc"
binding="wsHttpBinding"
bindingConfiguration="MyBindingConfig"
behaviorConfiguration="MyBehaviorConfig"
contract="Service.ICalculator"
name="ICalculatorServiceEndpoint">
<identity>
<servicePrincipalName value="host"/>
</identity>
</endpoint>
</client>
Server:
<behaviors>
<serviceBehaviors>
<behavior name="myBehavior">
<serviceCredentials>
<serviceCertificate findValue="CN=MyTestRootCA"
storeLocation="LocalMachine"
x509FindType="FindBySubjectDistinguishedName"/>
<userNameAuthentication userNamePasswordValidationMode="Windows"/>
<clientCertificate>
<authentication certificateValidationMode="PeerOrChainTrust"/>
</clientCertificate>
</serviceCredentials>
<serviceMetadata httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<unity operationContextEnabled="true"
instanceContextEnabled="true"
contextChannelEnabled="true"
serviceHostBaseEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="MyBinding">
<security mode="TransportWithMessageCredential">
<transport realm=""/>
<message clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="Service.Calculator"
behaviorConfiguration="myBehavior">
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="MyBinding"
contract="Service.ICalculator" />
<endpoint address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange"
name="CalculatorServiceMex" />
</service>
</services>
"CN=MyTestRootCA" is the "Authority" the "Creating" certificate and I put him in the trusted root certificates on the localComputer as well as in the personal directory in the local computer.
And it is the issuer of the client certificate "CN=MyTestClientCertificate".
Few things..
I know that the client certificate should be in the CurretUser directory in the "MMC" but when its there i have an exception that the app can't find the certificate.
I tried locating it by "FindBySubjectDistinguishedName" and with "FindByThumbprint", both time was the same exception "Cant find certificate with the given criteria ..." so i put it in the LocalMachine and its fine.
Any one has an idea why it didn't work?
I had lots of problems and exceptions with this =\ the current one is:
"The private key is not presented in the X.509 certificate"
Anybody familiar with this exception and know how to fix it?
thanks a lot for your answers, i'm sitting on this for few days now
Your configuration file does not specify the clientCertificate storeLocation value, therefore the client certificate needs to be in the LocalMachine store, which is the default value for storeLocation.
Consider the following example from msdn which sets the client certificate store location:
<clientCertificate>
<certificate
findValue="www.cohowinery.com"
storeLocation="CurrentUser"
storeName="TrustedPeople"
x509FindType="FindByIssuerName" />
<authentication …
Note: the other error, “The private key is not presented in the X.509 certificate”, is mostly likely thrown because your certificate does not have an associated private key or your process’ user context does not have permission to access the private key.

WCF service self hosting with https

Currenlty there is a Wcf service hosted as windows service in one of our client side machine, actually currently this is working with normal http call. As we need to use https instead of http, for that we modified app.config but after starting the service the https url not working.Then we tried URL reservation by using netsh http add urlacl url=https://+:18732/Peripheral/ user=Everyone.Then we restared the service again it's not able to access the https url.
we are getting the error in the URl browser •Make sure that TLS and SSL protocols are enabled.
Is this related to any certificate issue? if so how we can able to solve this issue?
The web.config is provied below:-
<system.serviceModel>
<standardEndpoints />
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<bindings>
<basicHttpBinding>
<binding name ="soapBinding">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
<webHttpBinding>
<binding name="Bind1" crossDomainScriptAccessEnabled="true">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="Peripheral.Server.Impl.PeripheralServiceImpl" behaviorConfiguration="SvcBhvr">
<host>
<baseAddresses>
<add baseAddress="https://localhost:18732/Peripheral/" />
</baseAddresses>
</host>
<endpoint address="https://localhost:18732/Peripheral/" binding="webHttpBinding" behaviorConfiguration="EndPBhvr" bindingConfiguration="Bind1"
contract="Peripheral.Server.Contract.IPeripheralService">
<!--<identity>
<dns value="localhost" />
</identity>-->
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="EndPBhvr">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="SvcBhvr">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Anyone knows how to fix this and what we needed to do so that we could able to access the url as https from windows services?
You may need also to bind ssl certificate to the specific port number using netsh or HttpConfig tool depending from OS version. Detailed instructions can be found here
In your case it could be:
netsh http add sslcert ipport=0.0.0.0:18732 certhash=<certhash> appid={<guid>} clientcertnegotiation=enable
where
certhash = your certificate Thumbprint(X509Certificate2.Thumbprint)
appid = could be just Guid.NewId()

Using X.509 Certificate with UserName clientCredentialType

I am creating a WCF service that requires a proxy username and password, in order to do this I need to provide a Service Certificate for which I have supplied our company Verisign Certificate which is valid.
The problem I am having is whenever I use the following configuration I get a error message "The service certificate is not provided. Specify a service certificate in ServiceCredentials."
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="false" />
<behaviors>
<serviceBehaviors>
<behavior name="WSBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate findValue="devstage1.vcg-online.net" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="TrustedPublisher" />
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Acre.IntegrationService.CustomValidator, Acre.IntegrationService" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Acre.IntegrationService.IntegrationService" behaviorConfiguration="WSBehaviour">
<endpoint address="http://localhost/Acre.IntegrationService/IntegrationService.svc"
binding="wsHttpBinding"
bindingConfiguration="WSBinding"
contract="Acre.IntegrationService.IIntegrationService"
name="WS" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="WSBinding" allowCookies="false">
<security mode="Message">
<message clientCredentialType="UserName" negotiateServiceCredential="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
UPDATED CONFIG
I have installed the certificate in the console using mmc.exe to the following paths
Certificates(Local Computer)/Personal/Certificates/
Certificates(Local Computer)/Trusted Root Certification Authorities/Certificates/
Certificates(Local Computer)/Trusted Publishers/Certificates/
I have searched the interweb and can not find a clear solution to my problem.
Can anyone help?
I have managed to fix the issue, #Rajesh you were correct with the clientCertificate needing to be serverCertificate, that corrected the error with not finding the certificate, thanks for that. The certificate was already installed on the machine for computer user.
The problem with the key set was the certificate did not have the correct account permission set to it. I changed the permisisons to allow the IIS_USRS to have access to the certificate and now it is fixed

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.

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.