How do you check the client certificate?

Hi,

Is it possible for the ServerEventsClient to send a client certificate for the server to check?

It looks like the JsonHttpClient can do it by creating a HttpClientHandler e.g.

HttpClientHandler httpMessageHandler = new HttpClientHandler()
{
    ServerCertificateCustomValidationCallback = (req, cert, chain, errors) =>
    {
		// TODO: Check server certificate is valid here
		return true;
    }
};

// TODO: Add client certificate here
// httpMessageHandler.ClientCertificates.Add()
httpMessageHandler.ClientCertificateOptions = ClientCertificateOption.Manual;

jsonClient = new JsonHttpClient(baseUri) {
	HttpMessageHandler = httpMessageHandler
};

I then need for my .NET Core server to be able to check the client certificate. How can this be done please?

I found the following article: https://stackoverflow.com/questions/24748769/how-to-authenticate-a-client-using-a-certificate-in-servicestack but when using the web new template e.g. web new web MyNewServer my .NET Core project cannot find ListenerRequest.

I am using CustomCredentialsAuthProvider if that makes any difference.

Thanks.

There’s no explicit support for client certificates in the ServerEventsClient, but you can access the WebRequest used in each of the Requests the ServerEventsClient makes and add it to the Request Filter with something like:

void AddClientCertificate(WebRequest req) =>
    ((HttpWebRequest)req).ClientCertificates.Add(...);

var sseClient = new ServerEventsClient(baseUrl) {
    EventStreamRequestFilter = AddClientCertificate,
    HeartbeatRequestFilter =  AddClientCertificate,
};
((JsonServiceClient) sseClient.ServiceClient).RequestFilter = AddClientCertificate;

To access the underlying Request object in all ServiceStack Hosts IRequest.OriginalRequest which you’d need to cast to HttpRequest in .NET Core, from their you can access the client certificate, e.g:

GlobalRequestFilters.Add((req,res,dto) => {
    var netcoreReq = (HttpRequest)req.OriginalRequest;
    var clientCert = netcoreReq.HttpContext.Connection.ClientCertificate;
});

Hi Demis,

That looks perfect, i’ll give that a go.

Thanks for your help.

Hi Demis,

When I try to access

the clientCert is null.

This happens for both my ServerEventsClient and my JsonHttpClient. If I break at the point of adding the certificate it all looks good i.e. it has read my pfx file using the password and I can see the subject etc at the client side.

I’m not 100% it is required for this but I have tried setting <access sslFlags="SslNegotiateCert" /> in the applicationhost.config for IIS Express and I also published it to full IIS with SSL Settings --> Client certificates set to Accept but it makes no difference, the clientCert object is still null.

The certificate has been ordered through RapidSSL so isn’t self signed and the pfx has the private key within it.

Do you know why this would be?

Thanks.

Hi, the above issue was because I thought I could get away with not installing the certificate and just point the client to the pfx file but after installing it the code works fine.

Hi Demis,

I notice on the server the certificate isn’t sent with the ServiceStack.UnRegisterEventSubscriber

Is there a RequestFilter for that where I can add the certificate?

Thanks.

I’ve added the UnRegisterRequestFilter in this commit, this change is available from v5.5.1 that’s now available on MyGet.

To make this easier to configure I’ve also added AllRequestFilters which you can configure once that gets run for all SSE requests which should your configuration down to just:

var sseClient = new ServerEventsClient(baseUrl) {
    AllRequestFilters = AddClientCertificate,
};

Hi, that looks great but how do I get the change you’ve made? I’m using NuGet Package ServiceStack.Client 5.5.1. Thanks.

You’ll need to clear your NuGet packages cache to download the latest version, e.g:

$ nuget locals all -clear