I want to limit the access to my .NET web service to a specific list of clients. They will attach their client certificate to their every request and only get a proper response if they are "on the list".
But how and where is the best way to implement this?
On the IIS (7.0) I can set the require client certificate option, but where do I specify which client certificates I will allow access? Do I need the public part of the client certificates in the certificate store of the web server machine?
Or must a setup like this be handled in code, where I somehow extract the client certificate ID and match it to a local list?
Or another way?
One way to create a WCF Service on IIS7 with your security requirements is as follows.
In order to host a WCF service you may need to run the following command on your web server:
"%windir%\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe" -r –y
On the IIS you set up your site with an https binding (only) and under SSL settings you set it to require SSL and require client certificates.
This alone will only allow access to your service (and wsdl) with a client certificate that is valid and with an issuer that is trusted by the web server.
In order to restrict access to specific certificates you could setup your WCF configuration file with a bindingConfiguration as:
<basicHttpBinding>
<binding name="MyBasicHttpBinding">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpBinding>
And a behaviorConfiguration with a custom certificate validator as:
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="Custom"
customCertificateValidatorType="<project-namespace>.ClientCertificateValidator, <project-namespace>"/>
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
And lastly implement the custom validator in a new class in your project as:
public class ClientCertificateValidator : X509CertificateValidator
{
public override void Validate(X509Certificate2 certificate)
{
if (certificate.Thumbprint != <allowed-thumbprint>)
throw new Exception();
}
}
If these client certificates originates from a specific root CA, you can propably use a CTL.
Otherwise I think you have these options (depending on your needs):
- If you have access to the client cert .cer files, you can use client certificate mapping and map to Windows account(s), optinally group them into AD/local groups and permission accordingly.
- Extract the UPN in code (perhaps in a HTTP handler) and verify against a list of granted UPN's