Question

I'm trying to get mutual SSL authentication working with ServiceStack, which under the hood uses HttpListener.

I use this command on the server to bind the server certificate to the required port, and enable client certificates:

netsh http add sslcert ipport=0.0.0.0:1234 certhash=5d51087438cbea33f2a4d86214b11a866876b9c5 appid={00000000-1111-2222-3333-444444444444} clientcertnegotiation=enable

If I run this command I can confirm that it says Negotiate Client Certificate : Enabled:

netsh http show sslcert

Then I add a reservation for the namespace using:

netsh http add urlacl url=https://+:1234/ user="NT AUTHORITY\NETWORK SERVICE"

'Normal' server authentication seems to work fine; the client is receiving the server's certificate and I can use ServicePointManager.ServerCertificateValidationCallback to override what is trusted.

But if the client sends no client certificate, it works as normal. If the client sends a client certificate (whether trusted or untrusted by the server), it still works as normal. This is of course not right!

I'm adding the client certificate using HttpWebRequest.ClientCertificates.Add(X509Certificate).

I've taken a look at the traffic on the wire, and AFAICS the server is sending a list of trusted CAs and requesting a client certificate.

Do I need to override something at the server to perform verification of the certificate sent by the client, similar to how clients can use ServicePointManager.ServerCertificateValidationCallback to verify the server certificate?

Was it helpful?

Solution

ServiceStack allows you to configure 'global filters', which can intercept all requests.

I solved my problem using a global filter:

public static void Validate(IRequest request, IResponse response, object message)
{
  var httpRequest = ((ListenerRequest)request).HttpRequest;
  var consoleCert = httpRequest.GetClientCertificate();
  ...

I can then send 403 if the client certificate is not present or is invalid:

response.StatusCode = 403;
response.EndRequest();
return;

Not sure if this is the recommended approach (or indeed if there is a recommended approach, but it works for me.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top