1

I have a WCF REST service application on .NET 4.7.2. Assume there's a method in the ServiceContract interface:

[ServiceContract]
public interface MyService
{
    [OperationContract]
    [WebGet(UriTemplate = "DoSomething", ResponseFormat = WebMessageFormat.Json)]
    ResponseDto DoSomething();
}

Suppose the IIS running an implementation of this service is configured to accept only HTTPS connections with a client certificate. Also assume the DoSomething() implementation is strictly dependent on the TLS client certificate.

Is there a way I can retrieve this TLS client certificate inside the service implementation?

public class MyServiceImpl : MyService
{
    public ResponseDto DoSomething()
    {
        // Something like GetClientCertFromTlsSession() 
        // to get the X509Certificate2 instance?
    }
}

Note: Of course, I could pass the encoded client certificate as parameter to the DoSomething REST call, but then there's no obvious way to match the one being passed to the REST call and the one used to establish the TLS handshake.

NumberFour
  • 3,551
  • 8
  • 48
  • 72
  • Just due to my ignorance; but why are you sending the client certificate? – Stefan Dec 07 '18 at 10:16
  • 1
    I need to have mutually authenticated TLS channel to the service. Also the service needs to know the client certificate to properly do its work. – NumberFour Dec 07 '18 at 10:22
  • I assume you're configuring for client certificates in your binding configuration? – Damien_The_Unbeliever Dec 07 '18 at 10:23
  • 1
    [This question](https://stackoverflow.com/q/7528455/15498) seems to have a couple of answers outlining different possible approaches. – Damien_The_Unbeliever Dec 07 '18 at 10:28
  • @NumberFour: Thanks, I wans't aware that the actual certificate needed to be send. I was always under the assumption (oops) that a with the client request signed message was sufficient. – Stefan Dec 07 '18 at 10:32
  • @Damien_The_Unbeliever Currently there's `basicHttpsBinding` and for debug purposes the client certs are optional, not required. But that will certainly have to change. – NumberFour Dec 07 '18 at 10:36

1 Answers1

1

You should be able to get the X509 certificate like this:

X509Certificate2 cert = null;
try
{
    if (OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets.Count > 0)
    {
        cert = ((X509CertificateClaimSet)OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets[0]).X509Certificate;
    }
    else
    {
        throw new Exception("missing cert...");
    }
}
catch (Exception ex)
{
    //log something and handle exception
}
Popo
  • 2,402
  • 5
  • 33
  • 55
  • Is there a documentation that mentions the certifcate to be available at index 0 of the ClaimSets? – Mothupally Jul 05 '20 at 06:35
  • 1
    No, in this case there was only one cert, so it was getting the first one, which probably the case most of the time, you would need to add additional logic should their be more certs in order to find the cert needed. – Popo Jul 06 '20 at 23:44