I am upgrading a webservice from .Net 1.1 to WCF. The client that will connect to my new web service is a webservice itself and was designed using WSE3. I have no control over that webservice and it will not be changing.
Keeping that in mind, I needed to keep the same service endpoints and security the same so I designed this WCF service using wscf.blue (wsdl first) which has been helpful. If the client comments out their X509 message encryption code, our webservices communicate nicely. However, if they leave their X509 encryption in place, they receive the message:
"The header 'Security' from the namespace 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' was not understood by the recipient of this message, causing the message to not be processed. This error typically indicates that the sender of this message has enabled a communication protocol that the receiver cannot process. Please ensure that the configuration of the client's binding is consistent with the service's binding. : at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall) at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)"
On my service, I added a message inspector to a custom endpoint behavior and the AfterReceiveRequest is fired but it never gets to the actual web service's method call.
I'm assuming my web.config needs changed but I do not know what to change it to so that a legacy WSE3 web service will understand. Any ideas will be helpful:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviorUnsecure">
<serviceCredentials>
<serviceCertificate storeLocation="LocalMachine" x509FindType="FindByThumbprint" findValue="xx 11 bb xx as bd ef ag r2 xx xx xx xx xx xx 12 34 56 78 90"/>
</serviceCredentials>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="TestContextEndpointBehavior">
<TestContextEndpointBehaviorExtensionElement />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="WebSoap" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="MyWebservice.MyNamespace.WebSoap" behaviorConfiguration="ServiceBehaviorUnsecure">
<endpoint address="http://localhost:6380/WebSoap.svc" behaviorConfiguration="TestContextEndpointBehavior"
binding="basicHttpBinding" bindingConfiguration="WebSoap"
contract="IWebSoap" />
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>
</services>
<extensions>
<behaviorExtensions>
<add name="TestContextEndpointBehaviorExtensionElement"
type="MyWebService.TestContextEndpointBehaviorExtensionElement, MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
</configuration>
**Edit**
I was able to get a portion of code from the client as to what they were doing to connect to secure the soap headers in the old web service. I also found a web page that is suppose to help but it leaves more questions. It states to select the authentication mode. One option is AnonymousForCertificate and another Mutual Certificate. If you select one of those options on the page to view, it leads you to the enumeration type and one that seems possible is CertificateOverTransport. I'm not if any one of these three would help. For example, we're using SSL so CertificateOverTransport seems viable but it says that it expects X.509 version 3 certificate. How am I suppose to know what version of X509? Maybe the code below will help you help me:
public bool EncryptAndSignMessage(string sSigningMachine, string sEncryptingMachine, ref SoapContext scSoapContext)
{
//sSigningMachine is the WSE client's machine name and sEncryptingMachine is my WCF's IIS server machine.
//For breavity, removed code to get byHasCodeSigning and byHashCodeEncrypting values. These are essentially the thumprints for the WSE's server's certificate and my WCF's server certificate.
X509SecurityToken securityTokenForSigning = this.GetSecurityTokenForSigning(byHashCodeSigning);
X509SecurityToken securityTokenForEncrypting = this.GetSecurityTokenForEncrypting(byHashCodeEncryption);
// SPECIFY TIME-TO-LIVE (TTL) FOR SOAP MESSAGE TO MINIMIZE RISK OF SOMEONE INTERCEPTING AND REPLAYING IT
scSoapContext.Security.Timestamp.TtlInSeconds = 60;
// ADD THE CLIENT'S X.509 CERTIFICATES TO THE WS-SECURITY SOAP HEADER
scSoapContext.Security.Tokens.Add(securityTokenForSigning);
scSoapContext.Security.Tokens.Add(securityTokenForEncrypting);
// CREATE NEW INSTANCE OF THE MESSAGE SIGNATURE CLASS AND ADD THE DIGITAL SIGNATURE TO THE WS-SECURITY SOAP HEADER
MessageSignature sig = new MessageSignature(securityTokenForSigning);
scSoapContext.Security.Elements.Add(sig);
// CREATE NEW INSTANCE OF THE ENCRYPTED DATA CLASS AND ADD THE SECURITY TOKEN FOR ENCRYPTING TO THE WS-SECURITY SOAP HEADER
EncryptedData enc = new EncryptedData(securityTokenForEncrypting);
scSoapContext.Security.Elements.Add(enc);
return true;
}
}