I transfered a workking WCF service from my development environment to the QA environment, including the certificates (Root Authority, Root Auth revocation list, Service certificate - including its PK).
Afterward I located the private key usihg 'FindPrivateKey' and gave all the relavent accounts full permissions to access the private key file at the file system level.
My app crashes with a Unhandled Exception: System.InvalidOperationException: Cannot load the X.509 certificate identity specified in the configuration.
I am stumped, I think I covered everything, but obviously not...
I have tried this on a Windows Service Host as well as a Console App Host. Same issue.
I ran into this same error in a simple WFC service written with VS2010 SP1 on Win 7. The fix that I found was to add
<dns value="localhost" />
to the <identity> section of app.config
Source: http://social.msdn.microsoft.com/Forums/en-AU/wcf/thread/439539ef-e8d7-4e7d-b36e-b80acd401606
this works for me :
<identity>
<certificateReference storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName" findValue="xxxxxxxx" />
<dns value="localhost" />
</identity>
Here's a tutorial explaining how to create a certificate that is supposed to remedy this problem:
Codeplex WCF Security: How To Create and Install Temporary Certificates in WCF for Message Security During Development.
Hope that fixes what you needed - even though you asked this 6+ months ago!
Regards,
Joe
Does your certificate common name match your host domain name?
I'm new to WCF and ran into this issue today when creating a simple WCF service. Just want to share some thoughts:
1. Fixing the issue - If you've read all other answers before Joe's (above) you'd know how to fix the issue ;) without the certificates
2. Fixing the issue with Certificates - I want to thank Joe for sharing a great link "How To: Create and Install Temporary Certificates in WCF for Message Security During Development"
Additionally: You can download WCF samples from Microsoft website.. You'll find a tool called 'FindPrivateKey' used in the above link
Related
The server is in workgroup (not domain). The self-hosted WCF service is configured with Windows security. Binding is netTcpBinding.
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
</security>
The WCF client runs on the same server.
A server certificate is used to encrypt traffic (probably it does not matter)
I implemented a simple test program. Everything works fine.
But when I implement it in our product, client cannot login. In event log I see an Audit Failure:
Failure Information:
Failure Reason: An Error occured during Logon
Status: 0xc000006d
Sub Status: 0x0
By googling I located this page for workaround: http://support.microsoft.com/kb/896861
After disable loopback check in registry, the logon succeed.
But I don't want to disable loopback check security in production environment. I need to find out the cause of this problem.
My question is: why my test program works fine but the product, which exposes multiple endpoints, hits the problem with loopback check security? Is there some WCF component/configuration that causes this problem?
More info: For testing I created a simple wcf client against my product. The test client call is authenticated successfully with loopback check enabled. Seems to me the problem is at wcf client side... Any idea?
Found my issue: I used a self-signed certificate with CN="WCF Security". The endpoints on both server and client have "identity" defined as:
<identity>
<dns value="WCF Security" />
</identity>
After changing to
<dns value="localhost" />
or even completely removing "identity", logon now succeeds without disabling Loopback Check Security.
I don't fully understand the relationship between the endpoint identity and certificate CN though.
I'm trying to make it so my Send Port which is of type WCF-BasicHttp, will send a client certificate that will be accepted by the IIS server of the WCF service.
So far, as far as I can tell, the Client Cert is being attached (because when I put the wrong thumbprint value in there, I get a "Client Cert not found error"). However, now I'm getting an error as such
System.Net.WebException: The underlying connection was closed: Could
not establish trust relationship for the SSL/TLS secure channel. --->
System.Security.Authentication.AuthenticationException: The remote
certificate is invalid according to the validation procedure.
Which to me, sounds like something in processing the IIS SSL certificate is not working.
This service
works fine when being called from another Winforms application, using
the same Client Cert.
is set to Require SSL
is set to Require Client Certificates
Have a look at the image below...the only way I was able to the WCF to recognize a client cert was being attached was through configuring the send port as such:
My question is, does this look correct? Notice the highlighted field, what is supposed to go in there? Is this the reason I'm getting the SSL/TLS error?
EDIT Or, do I have it all wrong, and the lower Certificate Reference area is not supposed to contain the Client Certficate?
So, it turns out, that in order to get it to work, I had to provide the Service's identity in the top portion. I noticed that putting anything in the Endpoint Identity dialog, after saving, a nice little bit of XML is written to the WCF-BasicHttp dialog after.
<identity>
<dns value="myserver.mydomain.ca" />
<certificateReference storeName="My" storeLocation="LocalMachine" x509FindType="FindByThumbprint" findValue="[thumbprint]" isChainIncluded="False" />
</identity>
with only the lower portion filled out as in my question above, it provides the <certificateReference> portion, but the <dns value="myserver.mydomain.ca" /> does not show up until you provide something in one of the textboxes in the "General" section. It worked when I provided either the DNS, or the Base64 of the server certificate.
So, I guess the answer is, once you fill out one of the sections, both are required, the send port is not going to automatically guess on the endpoint based on the address.
WCF is extremely extensible and has a lot of ready-to-use features, however I continue struggling with some topics and the more documentation I read, the more I get confused.
I hope to get some answers from the community. Feedback on any assumption or question is extremely welcome.
For the record: to really accept a single answer I should divide this post in multiple questions but it would lead to even more confusion.
I am pretty sure there are some real WCF experts online who can answer the few questions in this document all at once so I can accept a single answer as the real deal to setup clientcertificate authentication using IIS the right way.
Let me sketch the situation and partner request:
1: The partner requirement and the question to use a client certificate.
Partner X needs to call an API on my backend and they have the clear requirement to use Clientcertificate authentication.
They created the clientcertificate and provided us the certificate with only the public key since it seems only logic they keep the private key actually private and in their own system(s).
The certificate was imported on the local computer account and looking at the certification path this is valid. All intermediate certification authorities and in the end the root certification authority are trusted.
2: Our WCF serverside configuration
I have a serviceBehavior configured as such:
<behavior name="ClientCertificateBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceCredentials>
<serviceCertificate findValue="<serialnumber here>" x509FindType="FindBySerialNumber" />
<clientCertificate>
<authentication certificateValidationMode="PeerTrust" />
</clientCertificate>
</serviceCredentials>
</behavior>
I guess I made a first mistake here and should use ChainTrust to actually validate the certificate using its certification path. What do you think?
The service is configured as such:
<service behaviorConfiguration="ClientCertificateBehavior" name="<Full service namespace and servicename>">
<endpoint binding="basicHttpBinding" bindingConfiguration="Soap11CertificateBasicHttpBinding"
contract="<The interface>"></endpoint>
</service>
The binding looks like this:
It is a basicHttpBinding to force SOAP1.1 (according to the partner's specifications).
<binding name="Soap11CertificateBasicHttpBinding">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
3: Hosting the WCF service in IIS and the IIS configuration
We host our WCF services in IIS7.
We configured the folder in which the services reside to require SSL and to accept Client certificates.
Authentication-wise anonymous authentication is enabled.
The thing is that communication from the partner works and we were confident that everything was OK, however toggling the IIS-setting to 'require' client certificate shows us that all of a sudden it is no longer possible to successfully call our service.
Am I correct to assume that following things are not done correctly:
The serviceCerticate in the serviceBehavior is not really necessary. This is a setting used by the client. Or is it necessary to provide this certificate information for the service endpoint to match the certificate that's being send by the client?
For clientcertificate authentication to really work in IIS the certificate needs to be mapped to a user. This user should be granted permissions on the folder containing the services and all authentication mechanisms (anonymous, windows,...) should be disabled.
This way IIS will handle the actual handshake and validate the servicecommunication.
Or is it more a matter of extra security mapping the certificate to a user?
By setting 'Accept' on IIS we bypass the actual certificate validation between client and server.
All authentication mechanisms like 'anonymous' and 'windows' have to be disabled on IIS for the folder which holds the services.
In your scenario, you don't need to configure certificates in WCF, IIS handles those for you. You can clear the entire <serviceCredentials> block, because:
The <serviceCertificate> of <serviceCredentials> specifies an X.509 certificate that will be used to authenticate the service to clients using Message security mode, which you do not use, and the <clientCertificate> of <serviceCredentials> defines an X.509 certificate used to sign and encrypt messages to a client form a service in a duplex communication pattern.
See here how to map client certificates to user accounts.
How can I specify the service identity principal name in the WCF client config for the issuer STS when binding using WS-Federation?
I have an application pool running under a domain account on a front end server trying to authenticate using federation to backend services on an app server (running under domain accnts) using an STS also running on the app server and under a domain account.
In order to use Kerberos correctly I need to set the userprincipal name of the STS on the frontend client. I can't see how to do that.
I am experiencing a connected problem, which is that fallback to NTLM does not work when the issuer is specified using FQDN, and Kerberos fails (SSPI negotiation failed) I think because I have no issuer principal name in the config. If I set the issuer using IP address instead, then authentication to STS succeeds using NTLM, I think, so I have a workaround.
The STS is issuing tokens on the basis of Windows auth on that endpoint. It has other endpoints for forms-type auth and so on.
Possibly a related problem on our network is that silverlight clients that call back to web services are not working without the servers being manually added to Local Intranet zone in IE. Seems as though for some reason the app servers are not considered as being on same domain. Any clues much appreciated!
I found the solution regarding setting the user principal name of the STS. I just needed to set it in the issuer element of the federation binding:
OK, don't know why I couldn't find this before, but first thing Monday morning the answer pops up immediately:
http://msdn.microsoft.com/en-us/library/aa347735.aspx
The issuer element of the wsfederation is an endpoint config that allows you to set the user principal name within it.
The schema from the link above is here:
<issuer address="Uri" >
<headers>
<add name="String"
namespace="String" />
</headers>
<identity>
<certificate encodedValue="String"/>
<certificateReference findValue="String"
isChainIncluded="Boolean"
storeName="AddressBook/AuthRoot/CertificateAuthority/Disallowed/My/Root/TrustedPeople/TrustedPublisher"
storeLocation="LocalMachine/CurrentUser"
x509FindType=System.Security.Cryptography.X509certificates.X509findtype/>
<dns value="String"/>
<rsa value="String"/>
<servicePrincipalName value="String"/>
<usePrincipalName value="String"/>
</identity>
</issuer>
Regarding the network issues, this was a DNS problem. PTR used instead of aliases.
I've got a small WCF webservice working with the built-in WCF Service Host and with hosting by the Visual Studio 2008 built-in development webserver.
I these hosting enviroments I have relied on the WCF Test Client for invoking the service methods.
Now I am running into problems with my next phase of testing:
I have it hosted in IIS 5.1 on my WinXP dev machine and I think maybe the problem is I cannot continue to use WCF Test Client anymore. Here is what's happening:
Case 1: "Anonymous Access" is CHECKED (ENABLED)
WCF Test Client UI comes up properly, exposing the WebMethods and the INVOKE button.
Yet when I click INVOKE it fails to connect with a backend data store (a 3rd party product) that requires Windows authentication. I could post the error I get back from the product.DLL but I don't think it is relevant.
Case 2: "Anonymous Access" is un-CHECKED (DISABLED)
WCF Test Client UI fails to even initialize properly. My researching of this tells me that MEX (WS-Metadata Exchange) requires "Anonymous Access" and (apparently) WCF Test Client requires MEX. Here are key snippets of the error being returned:
Error: Cannot obtain Metadata from http://localhost/wcfiishost
The remote server returned an error: (401) Unauthorized.HTTP GET Error
URI: http://localhost/wcfiishost
There was an error downloading 'http://localhost/wcfiishost'.
The request failed with the error message:
Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service
The are lots of explanations of binding options, message security, etc. and stuff I honestly do not understand. Here is my take on where I am but I would love your opinions:
(a) Because I know my WCF webservice MUST be configured to use Windows Authentication, I conclude I cannot continue to use the WCF Test Client when hosting my service in IIS. That it has effectively outlived it's usefulness to me. I will just have to take the time to write a web client because WCFTestClient won't work without Anonymous.
(or)
(b) It is possible to use WCF Test Client if it and the hosted service are configured propertly (I just don't know what the special configuration techniques are for this).
Which is correct? Time to stop using WCFTestClient or is there a way to have it both ways? Thanks in advance for your advice.
EDIT: 11 June 09
Is there anything else I can provide to help someone else help me on this question?
I just tried to have the same setup - but in my case, everything seems to work just fine.
ASP.NET web site
WCF service, using basicHttpBinding without any special settings at all
IIS Application with anonymous = enabled and Windows authentication = enabled (both turned on)
I can easily connect to it with the WcfTestClient and retrieve the metadata, and I can then call it, no problem.
Inside my service function, I check to see whether the current user is a known user or not, it is correctly identified as a Windows authenticated user:
ServiceSecurityContext ssc = ServiceSecurityContext.Current;
if (ssc.IsAnonymous)
{
return "anonymous user";
}
else
{
if(ssc.WindowsIdentity != null)
{
return ssc.WindowsIdentity.Name;
}
if (ssc.PrimaryIdentity != null)
{
return ssc.PrimaryIdentity.Name;
}
}
return "(no known user)";
I don't really know, what more to check for (except I'm on Vista with IIS7). Any chance you could include this code to check for the user in your service code? Just to see....
Marc
Marc, your setup is not even close to Johns.
John uses WSHttpBinding that uses Windows Credentials for Message mode transport. The Windows Authentication isn't being used with BasicHttpBinding. Furthermore, John had AnonymousAuthentication disabled, which is why the Metadata Exchange (mex) is failing.
The call won't even reach inside the service side function, because we get a Error 401 (Unauthorized) when we try to call.
Just know John, I have the same issue, and I'm trying to somehow set up separate bindings per endpoint. Hopefully that will work.
When I set the title/subject of this question and reached a dead end here, I opened up the same issue in the MSDN forum with a different emphasis on the title (content of question essentially the same).
For me, the real issue was how to use WCFTestClient in IIS without Anonymous Authentication being set (because my service needed Integrated Windows Authentication only).
Mex apparently requires Anonymous and by default WCFTestClient seems to need Mex. The key seems to be accomodating both my doctoring up the web.config file carefully.
Anyway, I got it working with this web.config below (the MSDN link is here:
<?xml version="1.0"?>
<configuration>
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="wsBindingConfig"
contract="sdkTrimFileServiceWCF.IFileService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="basic"
binding="basicHttpBinding"
bindingConfiguration="bindingConfig"
contract="sdkTrimFileServiceWCF.IFileService" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="bindingConfig">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpBinding>
<wsHttpBinding>
<binding name="wsBindingConfig">
<security mode="Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
</serviceBehaviors>
</behaviors>