My GUI application controls its sister Windows Service using WCF's NetNamedPipeBinding
. I want to prevent other applications from impersonating my GUI application and controlling my service.
Is it necessary to authenticate the GUI application to the Windows Service to prevent impersonation?
And how should I go about it?
Edit: Remote computers should also be able to control the service given that they are authenticated (trusted by the service), so I need to add a NetTcpBinding
endpoint. Any answer that incorporates this as well, would be helpful.
Yes, it is necessary to secure the WCF channel to prevent impersonation. WCF can encrypt your communications automatically when you instruct it to, but you need to handle the authentication part yourself.
There are two methods of securing messages in WCF (three if you count the fact that you can use both of them at once). There is a good high level explanation here. Which of these methods you can use is dependent on which binding we are talking about (you will have different options for different bindings).
Furthermore, for each method of securing the service you will have a choice between authentication credential types (the actual means in which each entity will prove its identity to the other endpoint). This is dependent on the binding and also on the security method.
To see what your options are for each binding, you can check its Security
property. This property is of a different type for each binding (e.g. NetTcpSecurity
); you can check MSDN or IntelliSense to find this out.
I will be using NetTcpBinding
with transport security as an example from now on.
To set up security, both in the server and client part, you first have to configure the binding with the security mode and authentication type before creating and opening the channel, e.g.:
var binding = new NetTcpBinding { /* set props here */ };
// TLS security with X.509 certificates
binding.Security.Mode = SecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate;
Then, on the server side (this example is specific to the choices made above):
// Load and set the server certificate
var serverCertificate = new X509Certificate2(/* parameters here */);
host.Credentials.ServiceCertificate.Certificate = serverCertificate;
// You can leave it at that and let Windows validate the client's certificate using
// the default method (which means that you either need to have added the client's
// certificate to the server machine's certificate store as "trusted", or rely on chain
// trust and have the client's certificate signed by a trusted authority.
// Or, you can use custom validation rules:
var authentication = host.Credentials.ClientCertificate.Authentication;
authentication.CertificateValidationMode = X509CertificateValidationMode.Custom;
authentication.CustomCertificateValidator = new AcceptAnythingCertificateValidator();
And on the client side (this example is also specific):
var clientCertificate = new X509Certificate2(/* parameters here */);
var factory = new ChannelFactory<IYourServiceInterface>(binding, endpoint);
factory.Credentials.ClientCertificate.Certificate = clientCertificate;
// You can leave it at that and let Windows validate the server's certificate using
// the default method (which means that you either need to have added the server's
// certificate to the client machine's certificate store as "trusted", or rely on chain
// trust and have the server's certificate signed by a trusted authority.
// Or, you can use custom validation rules:
var authentication = factory.Credentials.ServiceCertificate.Authentication;
authentication.CertificateValidationMode = X509CertificateValidationMode.Custom;
authentication.CustomCertificateValidator = new AcceptAnythingCertificateValidator();
var channel = factory.CreateChannel();
// Your channel is now ready for use! You can also cast to to IClientChannel
// to expose some more properties.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With