Requiring SSL certificates and client certificates throws exception in WCF JSON service

I have a simple WCF service setup that uses JSON. In this service, I want to use client authentication with a client certificate. I configured IIS 6 to require SSL and require client certificates by setting the folder / site / services / wcf / json /. This setting is usually called 2-way SSL.

But I get an exception when I try to verify the page using the generated SSL certificate.

The SSL settings for the No service do not match the SSL, Ssl, SslNegotiateCert, SslRequireCert settings.

Stack Trace: [NotSupportedException: The SSL settings for the service 'None' does not match those of the IIS 'Ssl, SslNegotiateCert, SslRequireCert'.] System.ServiceModel.Activation.HostedAspNetEnvironment.ValidateHttpsSettings(String virtualPath, Nullable`1& requireClientCertificate) +117347 System.ServiceModel.Channels.HttpsChannelListener.ApplyHostedContext(String virtualPath, Boolean isMetadataListener) +97 System.ServiceModel.Activation.HostedAspNetEnvironment.ApplyHostedContext(TransportChannelListener listener, BindingContext context) +84 System.ServiceModel.Channels.HttpsTransportBindingElement.BuildChannelListener(BindingContext context) +93 System.ServiceModel.Channels.BindingContext.BuildInnerChannelListener() +63 System.ServiceModel.Channels.MessageEncodingBindingElement.InternalBuildChannelListener(BindingContext context) +67 System.ServiceModel.Channels.WebMessageEncodingBindingElement.BuildChannelListener(BindingContext context) +49 System.ServiceModel.Channels.BindingContext.BuildInnerChannelListener() +63 System.ServiceModel.Channels.Binding.BuildChannelListener(Uri listenUriBaseAddress, String listenUriRelativeAddress, ListenUriMode listenUriMode, BindingParameterCollection parameters) +125 System.ServiceModel.Description.DispatcherBuilder.MaybeCreateListener(Boolean actuallyCreate, Type[] supportedChannels, Binding binding, BindingParameterCollection parameters, Uri listenUriBaseAddress, String listenUriRelativeAddress, ListenUriMode listenUriMode, ServiceThrottle throttle, IChannelListener& result, Boolean supportContextSession) +337 System.ServiceModel.Description.DispatcherBuilder.BuildChannelListener(StuffPerListenUriInfo stuff, ServiceHostBase serviceHost, Uri listenUri, ListenUriMode listenUriMode, Boolean supportContextSession, IChannelListener& result) +668 System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost) +1228 System.ServiceModel.ServiceHostBase.InitializeRuntime() +60 System.ServiceModel.ServiceHostBase.OnBeginOpen() +27 System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +50 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +318 System.ServiceModel.Channels.CommunicationObject.Open() +36 System.ServiceModel.HostingManager.ActivateService(String normalizedVirtualPath) +184 System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath) +615 

I tested that the certificates are installed correctly. I created a base virtual directory that requires client authorization. This virtual directory contains a simple .htm file. I confirmed that it requires https and that it challenges me for my client certificate, and when I proved that it is a valid client certificate, it displays the .htm page, and when I did not prove a valid certificate, it is not.

When applying the same settings in IIS to my WCF service, I get the exception above. I tried to configure services to also require SSL and client authorization, but I keep getting the exception above.

Here are my settings.

 <system.serviceModel> <!-- behaviors --> <behaviors> <endpointBehaviors> <behavior name="jsonBehavior"> <enableWebScript /> <clientCredentials> <clientCertificate findValue="*.MyCompany.com" storeLocation="LocalMachine" x509FindType="FindBySubjectName" storeName="My" /> </clientCredentials> </behavior> </endpointBehaviors> <serviceBehaviors> <behavior name=""> <serviceDebug includeExceptionDetailInFaults="true" /> <serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" /> <serviceCredentials> <serviceCertificate findValue="*.MyCompany.com" storeLocation="LocalMachine" x509FindType="FindBySubjectName" storeName="My" /> </serviceCredentials> </behavior> </serviceBehaviors> </behaviors> <!-- bindings --> <bindings> <webHttpBinding> <binding name="webBinding"> <security mode="Transport"> <transport clientCredentialType="Certificate"/> </security> </binding> </webHttpBinding> </bindings> <!-- services --> <services> <service name="Service1Json" behaviorConfiguration=""> <endpoint address="https://www.MyCompany.com/site/services/wcf/json/Service1.svc" behaviorConfiguration="jsonBehavior" binding="webHttpBinding" bindingConfiguration="webBinding" contract="MyCompany.Services.Wcf.IService1" /> </service> <service name="Service2Json" behaviorConfiguration=""> <endpoint address="https://www.MyCompany.com/site/Services/WCF/json/Service2.svc" behaviorConfiguration="jsonBehavior" binding="webHttpBinding" bindingConfiguration="webBinding" contract="MyCompany.Services.Wcf.IService2" /> </service> <service name="Service3Json" behaviorConfiguration=""> <endpoint address="https://www.MyCompany.com/site/services/wcf/json/Service3.svc" behaviorConfiguration="jsonBehavior" binding="webHttpBinding" bindingConfiguration="webBinding" contract="MyCompany.Services.Wcf.IService3" /> </service> </services> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> </system.serviceModel> 
+4
source share
1 answer

The problem actually turned out to be more complicated than I describe above. And the resulting solution was quite simple.

The original problem did not mention that we have several endpoints: 1. SOAP 2. JSON. They must be secured by two-way SSL.

Our mistakes were as follows:

  • Client and server credentials are not required.
  • The service name must match the .svc file name.
  • Endpoint addresses must be different. So, for our JSON endpoint, we added "json". We also removed the full URI from the address and let WCF automatically generate it for us.

Here is the final configuration we ended up with:

 <system.serviceModel> <!-- behaviors --> <behaviors> <endpointBehaviors> <behavior name="jsonBehavior"> <enableWebScript /> </behavior> </endpointBehaviors> <serviceBehaviors> <behavior name=""> <serviceDebug includeExceptionDetailInFaults="true" /> <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" /> </behavior> </serviceBehaviors> </behaviors> <!-- bindings --> <bindings> <basicHttpBinding> <binding name="httpBinding"> <security mode="None"> </security> </binding> </basicHttpBinding> <webHttpBinding> <binding name="webBinding"> <security mode="None"> </security> </binding> </webHttpBinding> </bindings> <!-- services --> <services> <service name="MyCompany.Services.Wcf.Service1" behaviorConfiguration=""> <endpoint address="json" behaviorConfiguration="jsonBehavior" binding="webHttpBinding" bindingConfiguration="webBinding" contract="MyCompany.Services.Wcf.IService1" /> <endpoint address="" behaviorConfiguration="" binding="basicHttpBinding" bindingConfiguration="httpBinding" contract="MyCompany.Services.Wcf.IService1" /> </service> <service name="MyCompany.Services.Wcf.Service2" behaviorConfiguration=""> <endpoint address="json" behaviorConfiguration="jsonBehavior" binding="webHttpBinding" bindingConfiguration="webBinding" contract="MyCompany.Services.Wcf.IService2" /> <endpoint address="" behaviorConfiguration="" binding="basicHttpBinding" bindingConfiguration="httpBinding" contract="MyCompany.Services.Wcf.IService2" /> </service> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> </system.serviceModel> 

If we had chosen so that SOAP did not use two-way SSL, and JSON required 2-way SSL, the configuration would be much more complicated.

+3
source

Source: https://habr.com/ru/post/1383761/


All Articles