WCF does not provide out-of-box authentication for each operation. If you want to ensure safe and insecure operations, the easiest way is to split them into two service contracts and set them up with different security settings.
Your idea of ββan authorization token has already been implemented in WCF, but in your scenario you should use the wsHttpBinding client credentials, UserName, SecurityContext certificate and service certificate.
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="securedService"> <serviceCredentials> <serviceCertificate x509FindType="FindBySubjectName" findValue="ServerCert" storeLocation="LocalMachine" storeName="My"/> </serviceCredentials> </behavior> </serviceBehaviors> </behaviors> <bindings> <wsHttpBinding> <binding name="Secured"> <security mode="Message"> <message clientCredentialType="UserName" establishSecurityContext="true" /> </security> </binding> </wsHttpBinding> </bindings> <services> <service name="MessageSecurity.Service" behaviorConfiguration="securedService"> <endpoint address="" binding="wsHttpBinding" bindingConfiguration="Secured" contract="MessageSecurity.IService"> </endpoint> </service> </services> </system.serviceModel>
SecurityContext is a compatible feature based on WS-SecureConversation. It requires you to skip the username and password only when you first call from the service proxy instance (in WCF this is completely transparent - the client proxy server supports the security context). The following calls use only the security token issued during the first call. SecurityContext is enabled by default in wsHttpBinding.
This configuration will also encrypt and sign messages - it is a full-featured WS-Security. Any other approach is up to you. You will have to fully implement it yourself.
You mentioned that you have no control over customers. This does not mean that you cannot use the certificate. If you use a certificate, it is the customerβs responsibility to receive it if they want to call you. This has nothing to do with customer control regarding trust in the certificate - for a public web service this means purchasing a certificate from a trusted certificate authority.
In addition, you can obtain a service certificate without installing it. The first option is to use the certificate as an endpoint identifier. In this case, the encoded certificate is part of the WSDL:
<wsdl:service name="Service"> <wsdl:port name="WSHttpBinding_IService" binding="tns:WSHttpBinding_IService"> <soap12:address location="http://localhost:1432/Service.svc" /> <wsa10:EndpointReference> <wsa10:Address>http://localhost:1432/Service.svc</wsa10:Address> <Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity"> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <X509Data> <X509Certificate>MIICmzCCAYegAwI....<X509Certificate> </X509Data> </KeyInfo> </Identity> </wsa10:EndpointReference> </wsdl:port> </wsdl:service>
This is done automatically if you specify the wsHttpBinding endpoint with the configured service certificate and do not set its identifier. The disadvantage of this method is the expiration of the certificate. If you are changing an expired certificate, all clients must be updated.
The second option is to enable reconciliation of service credentials:
<bindings> <wsHttpBinding> <binding name="Secured"> <security mode="Message"> <message clientCredentialType="UserName" negotiateServiceCredential="true"/> </security> </binding> </wsHttpBinding> </bindings>
Switching is enabled by default. It uses the TLSNego protocol to exchange service data (certificate) before starting secure communication. The disadvantage of this method is that TLSNego is not supported on all platforms.