WCF Client Certificate Authentication - wcf

We have a typical client-server WCF service and I would like the following:
Client passes a certificate to the Server through the ClientCredentials property
Server looks at the certificate and see's that it has been issued by our trusted certificate authority
The client is rejected if they use a certificate that is not issued by our CA.
The client has a clientAuthentication certificate installed, along with our trusted CA.
The server has our trusted CA certificate installed. I dont want to install any other certificates.
I am flexible on the binding, however it does need to work in a web scenerio.
I thought about using BasicHttpBinding with TransportCredentialOnly, however it doesnt support certificates :(.
Ive tried using wsHttpBinding in Message mode, however that requires a ServerCertificate to perform server authentication and message encryption... which I dont want!
Is there any built-in way to achieve this?

All build in bindings allow using client certificates only when server certificate is used - mutal certificate authentication and security. To support your scenario you will have to handle it completely yourselves. If you want to inject your authentication mechanism to WCF you will have to do custom token and custom credentials.

Related

Self signed client certificate does not reach server application

I have the following setup:
A self signed certificate for development purposes
An OWIN hosted Web API, deployed on a local Azure Service Fabric Cluster as a ASF service. The Web API uses HTTPS facilitated with the dev certificate in question.
A simple .net client application that calls the Web API. In that application the ServicePointManager.ServerCertificateValidationCallback method is set so it always returns true (since the CA is not trusted)
Both the client application and the Web API are on the same local development machine. The certificate is installed in that same machine on the "machine store"
Now I am able to make calls to the web api using Fiddler by providing the required client certificate. However when I try to do the same via .net code (be it RestSharp or WebRequest) the client certificate is not present in the RequestContext object on the server side. This result in an Unauthorized response. I do not think the problem is with the client code, the certificate is loaded correctly and assigned to the http client or request. Fiddler shows encrypted tunneling to the server. However the client certificate does not seem to be present at the server side.
I am at a complete loss regarding what am I missing that could cause this behavior. Any help will be deeply appreciated.
Install the certificate into the 'Local Machine/Trusted People'.
The server needs to already trust the certificate before it asks. The CertificateRequest message that it sends lists the acceptable CAs that can sign the client certificate. If the client certificate's signer isn't in that message, it can't send it.
How you accomplish that in your environment is left as an exercise for the reader. In general now that SSL certificates are available free there is little reason to indulge in the time costs and administrative inconveniences of self-signed certificates. IMHO there wasn't even if you were paying for a CA signature.
I had a problem when a service called another service over HTTPS and it couldn't setup a secure connection. My problem was that since the service is running as NETWORK SERVICE, it couldn't find the certificate, because it was looking in the localmachine/my certificate store.
When I was running from my web browser it was working fine because then, my browser found the certificate in the currectuser/my certificate store.
Add the certificate to the machine/my store and see if it helps.

How can I use a self-signed client certificate in a WCF call with transport security?

I have a WCF service (authored in-house) using a WS-HTTP binding and transport security (SSL). We are authenticating callers with client certificates and a whitelist of acceptable certificates (certs are provided to us out-of-band). So we're using a custom validator (e.g. a class deriving from System.IdentityModel.Selectors.X509CertificateValidator) to do a database query to check the whitelist.
It works in the following case: We have a root certificate used in development, issued by the development team (using OpenSSL). This root is trusted (e.g. installed in the Trusted Third-Party CA cert store) on the server hosting our WCF service. The test client is configured to present a certificate signed by this root. This case behaves as expected.
It does not work in the following case: The client presents a self-signed certificate to the service. In this case the client receives the error message "The HTTP request was forbidden with client authentication scheme 'Anonymous'", and-- here's the odd part-- the service's certificate validator doesn't even run. We don't get any chance to give the thumbs-up. The client cert is rejected by a layer lower than our validator.
How can I use a self-signed client certificate with my service?
You can't. In WCF, WS-HTTP transport security is SSL. My error results from a failure in the SSL negotiation between the parties.
The normal case of this negotiation is as follows: The service sends the client a list of root certificates that it trusts. The client examines this list and finds a certificate that the server will find trustworthy and sends it.
In my error case, the client is examining the server's list and determining that its cert will not be trusted. At this point the client will normally attempt to negotiate down to anonymous access, which is forbidden in my case, so the negotiation fails.
WCF does not support self-signed client certificates, or certs issued by an untrusted CA, in WS-HTTP binding + transport security scenarios, even if you use custom validation mode. It does support this scenario in message security. I suspect that Net.TCP supports this scenario, but haven't tested that.

WCF - Is a service certificate needed to authenticate clients?

I think there's a gap in my mental model of WCF authentication, hoping someone can help me fill it in.
So, I'm creating a WCF service and would like to have clients authenticate using certificates, and message-level security. I'd like the service to validate these using chain trust so that I don't need each client cert installed on the service. For now, I'm not interested in having the service authenticate to the client.
Here's my understanding of what's needed to do this:
The client needs a certificate signed by a CA that's trusted on the service side.
The service needs a CRL installed for that CA.
The service config should have message security turned on, specify clientCredentialType="Certificate", and chain trust for client certificate validation.
The client config should have message security turned on, specify clientCredentialType="Certificate", and an endpoint behavior that tells how to find the client certificate in the store.
The client makes a request to the service, sending its certificate. The service sees that the client's cert is signed by its trusted CA and lets the request through.
Now, all of the walkthroughs of this process I've found also include a step of creating a certificate for the service. None of them explain what this is for, which is throwing me. Why is a service certificate needed if I just want to authenticate the clients?
You are right. In theory no server certificate is required, in practice wcf enforce you to use one. The good news is that you should use a dummy certificate for the server and also set ProtectionLevel to SignOnly. I suggest to read this article which talks on a similar scenario and mostly relevant.

Can I Validate x509 ClientCertificate on a WCF web service?

Do not really know how x509 works.
If I have a Web Service that needs to authenticate and validate the client, and he uses a ClientCertificate, could he send me some information that I could then validate against?
I do not create the Web Site itself so I can't be sure they would do it right. I don't wan't to allow someone to say to the Web Service "It's okay, I ClientCertificated him and he's good".
You can implement your own custom client certificate validator but its usage will be different based on the way how do you use the client certificate. If you use pure message security your validator will be the only component used to validate the certificate. If you use HTTPS with client certificate (transport security) the certificate will be first validated by Windows (= your service hosting server must trust the certificate) and after that it will be passed to WCF and validated by your validator.

WCF WsHttpBinding Certificate Transport Security - Windows Certificate Configuration

I have two WCF Services using WsHttpBinding with transport security mutual certificate authentication that are being hosted on the same windows server. Clients that can access one WCF service should not have access to the other WCF service. I need some help on configuring the client certificates on the windows host. The client certificates are signed by trusted CAs and the intermediate and root certificate chain is already installed on the the server. It seems like the service automatically relies on chain of trust and does not require the actual client certificates installed on the server at all before letting the client access the service - this is not the behavior I want. Can someone please tell me how I should be configuring these client certificates in order explicitly allow access to one service and not the other?
Thanks.
That has nothing to do with certificates themselves. When using mutual SSL authentication certificates are used only to authenticate client and the authentication is done outside of your application (this is difference to message security where you can create custom certificate validator). Once certificate is trusted client is automatically authenticated to anything on the server using certificates for authentication.
You are looking for authorization - the step where you define what can authenticated client do with your service. You can either hardcode your authorization logic into your service by using role based security or you can implement two custom ServiceAuthorizationManagers and assign each to single service.