passing wsse security header with dynamicserviceproxy - header

I am trying to consume this service that requires wsse header as
<soapenv:Header>
<wsse:Security soapenv:actor="AppID" soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>domain1\UNM1</wsse:Username>
<wsse:Password wsse:Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">PWD1</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
I am creating proxy dynamically as
string[] assemblyReferences = new string[3] { "System.Web.Services.dll", "System.Xml.dll", "Microsoft.Web.Services3.dll" };
CompilerParameters parms = new CompilerParameters(assemblyReferences);
CompilerResults results = provider1.CompileAssemblyFromDom(parms, unit1);
if (results.Errors.Count > 0)
{
foreach (CompilerError oops in results.Errors)
{
Console.WriteLine("========Compiler error============");
Console.WriteLine(oops.ErrorText);
}
return;
}
//Invoke the web service method
object o = results.CompiledAssembly.CreateInstance("DynamicServiceProxy.servicename");
//object o = results.CompiledAssembly.CreateInstance("DynamicServiceProxy.WebService");
Type t = o.GetType();
BindingFlags bf = BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.DeclaredOnly;
MethodInfo m = t.GetMethod("Methodname", bf);
stroutput = (string) m.Invoke(o, new object[].....
How do I pass header to this. I did some research and installed WSE 3.0 and added reference for service3. However i am not able to get RequestSoapContext or clientcredential method in t. client(o) is being generated from soaphttpclientprotocol and not WebServicesClientProtocol and that should be cause of all problems. Please help.
Also since generating proxy dynamically , not sure i can do like
MessageServiceWse client = new MessageServiceWse()
Also I am not sure about wsse type . How to define this.
Just to note that I am using VS 2010
This is my first service experience so please excuse me in case I did some obvious mistake(s).
Need expert help.

changed end point to include header as it is common across request.
<endpoint address="https://wsext.test.com/gfr/ext/test1/"
binding="basicHttpBinding" bindingConfiguration="GLEditServiceSOAP"
contract="test1.GLEditServicePort" name="GLEditServicePort">
<headers >
<wsse:Security s:actor="AppID" s:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<wsse:UsernameToken>
<wsse:Username>test1\testuserid</wsse:Username>
<wsse:Password wsse:Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</headers>
</endpoint>

Related

WCF FaultCode MustUnderstand = 1 .net 4.0

How do I change my wcf service to be able to accept mustunderstand = 1?
This is a scenario where I have to change the service to be able to accept a request from the client. The client sends mustunderstand =1 in the header.
The service is configured to use basichttpBinding
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
<transport clientCredentialType="None"></transport>
</security>
Using soap UI I insert the following username token into the header
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-2684C13EA73A35131015516775308851">
<wsse:Username>username</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
I can reproduce the issue on soap UI when I insert this token in the wcf service request. This is the error
<FaultMsgRec>
<ErrCode>100</ErrCode>
<ErrCat>Error</ErrCat>
<ErrDesc>An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.--> 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. </ErrDesc>
</FaultMsgRec>
Since I have control over the wcf service I can go and add ValidateMustUnderstand = false in the service behavior.
Just like it is explained in the link
https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.description.mustunderstandbehavior.validatemustunderstand?view=netframework-4.7.2
Once I add this to the service behavior the error disappears.
But I don't want to turn off validation on the header especially if its a username, password. What should I do to allow mustunderstand=1? Am I missing something that the service doesn't automatically process mustunderstand=1 by default. I know there is code to be written on the client in order to sent a 0 in the header.
I am using message contracts in my wcf service not data contract. I understand that for certain properties I can go and add attributes like this link
https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.messageheaderattribute.mustunderstand?view=netframework-4.7.2. But I am not adding to any properties. I am just adding it to the first linke in soapenv:mustunderstand=1
Please help!.
Thank you
Not sure whether this could solve your problem. But you could try to add your header in web.config.
<endpoint address="http://ws-wuxipc-5077:4000/calculator" binding="basicHttpBinding"
contract="ServiceInterface.ICalculatorService" name="cal">
<headers>
<Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" >
<wsse:UsernameToken xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>
</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">monMonDePasse</wsse:Password>
<wsse:Nonce>sdsdsdlojhfdsdM5Nw==</wsse:Nonce>
<wsu:Created>2019-01-21T6:17:34Z</wsu:Created>
</wsse:UsernameToken>
</Security>
</headers>
</endpoint>
Or you could add header using code.
using (ChannelFactory<ICalculatorService> ChannelFactory = new ChannelFactory<ICalculatorService>("cal"))
{
ICalculatorService employeeService = ChannelFactory.CreateChannel();
using (OperationContextScope scope = new OperationContextScope((IContextChannel)employeeService))
{
System.Xml.XmlDocument document = new XmlDocument();
XmlElement element = document.CreateElement("wsse", "UsernameToken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
XmlElement newChild = null;
newChild = document.CreateElement("wsse", "Username", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
newChild.InnerText = "finance";
element.AppendChild(newChild);
newChild = document.CreateElement("wsse", "password", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
newChild.SetAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest");
newChild.InnerText = "387";
element.AppendChild(newChild);
MessageHeader messageHeader = MessageHeader.CreateHeader("security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", element, false); // here is mustunderstood is set to false
OperationContext.Current.OutgoingMessageHeaders.Add(messageHeader);
}
Console.Read();
}

Can I add this Custom WCF security node in SOAP header with WCF methods?

I have this SOAP flux that I need to send to a remote service, with a wsse:Security node that is expected to look like this:
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-5FJPET4ATPQZMREXU8C51DK9P6OTW022">
<wsse:Username>NotQuiteThatStupid</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">DonTBotherReadingThisNode</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
I've tried to do it with WCF, as it looks like the current standard and is rather well documented. Long story short, I couldn't find a way to make it work.
At the end of my wits, I took inspiration from http://blog.aggregatedintelligence.com/2010/06/wcf-transportwithmessagecredential-and.html and wrote my XML nodes directly into the header :
Dim z_bieTextBinding As TextMessageEncodingBindingElement = New TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8)
Dim z_bieHttpBinding As HttpTransportBindingElement = New HttpTransportBindingElement()
Dim z_cbiBinding As CustomBinding = New CustomBinding(z_bieTextBinding, z_bieHttpBinding)
Dim z_epaFinalAddress As EndpointAddress = New EndpointAddress("http://some.where.over/the/rainbow")
Dim z_chfChannels As ChannelFactory(Of IRequestChannel) = New ChannelFactory(Of IRequestChannel)(z_cbiBinding, z_epaFinalAddress)
Dim z_rqcChannel As IRequestChannel = z_chfChannels.CreateChannel()
z_rqcChannel.Open()
Dim z_msgToSend As Message = Message.CreateMessage(MessageVersion.Soap11, p_strActionName, p_objMessageBody)
Dim z_strUserHeader As String = "<wsse:UsernameToken " & _
"xmlns:wsse=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"" " & _
"xmlns:wsu=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"" " & _
"wsu:Id=""UsernameToken-5FJPET4ATPQZMREXU8C51DK9P6OTW022"">" & _
"<wsse:Username>NoOneYaKnowPardner</wsse:Username>" & _
"<wsse:Password Type=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"">DonTBotherPal</wsse:Password>" & _
"</wsse:UsernameToken>"
Dim z_xdoDocUserHeader As XmlDocument = New XmlDocument()
z_xdoDocUserHeader.LoadXml(z_strUserHeader)
Dim z_mheSecurityHeader As MessageHeader = MessageHeader.CreateHeader("Security", _
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", _
z_xdoDocUserHeader.DocumentElement)
z_msgToSend.Headers.Add(z_mheSecurityHeader)
It does work. (xmlns attributes are a bit different from the model, but they still pass.) Still, I can't shake the feeling that it should be feasible without resorting to XML manipulation. So :
Am I right to feel this is a "dirty" solution?
Is there an alternate way to do this using only WCF objects, properties and methods?
EDIT: I tried another approach. I set up bindings and endpoints in the Web.config thus:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="bndSimpleGeneric"
messageEncoding="Text"/>
</basicHttpBinding>
</bindings>
<client>
<endpoint name="enpBasicEndpoint"
address="http://dms-uat.athoris.net/Athoris"
binding="basicHttpBinding"
bindingConfiguration="bndSimpleGeneric"
contract="System.ServiceModel.Channels.IRequestChannel">
<headers>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>CanTRememberWho</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">SomethingSomethingOrangesSomething</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</headers>
</endpoint>
</client>
</system.serviceModel>
Which lets me have much simpler code:
Dim z_chfChannels As New ChannelFactory(Of IRequestChannel)("enpBasicEndpoint")
Dim z_rqcChannel As IRequestChannel = z_chfChannels.CreateChannel()
z_rqcChannel.Open()
Dim z_msgToSend As Message = Message.CreateMessage(MessageVersion.Soap11, "Action Name", "<MessageBody>Words</MessageBody>")
Dim z_mbuToSend As MessageBuffer = z_msgToSend.CreateBufferedCopy(Integer.MaxValue)
Dim z_msgResponse As Message = z_rqcChannel.Request(z_mbuToSend.CreateMessage())
z_rqcChannel.Close()
z_chfChannels.Close()
Return z_msgResponse
As indicated in the comments below, I'm not sure I should be satisfied with that since the username and, worse, the password are in the Web.config. Still, it looks much better (to me) than cobbling XML code together with character strings. As before, opinions on the matter are welcome.

WS-Security from soapUI to WCF - binding & configuration

I need to create a WCF client to call a service that I have no control over and we have been given a wsdl only (with schemas). The web service uses the X.509 certificate with the WS-Security specification version 1.0
The web service provider has shared raw xml of the soap message to highlight the ws-security header. Using the soapUI, I have been able to create the exact same wsse-Security header as shown below:
<soapenv:Envelope xmlns:oas="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:oas1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xd="http://www.w3.org/2000/09/xmldsig#">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<ds:Signature Id="SIG-32" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#id-31">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<InclusiveNamespaces PrefixList="oas oas1 urn urn1 urn2 urn3 xd" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>ucSFZEOTHpe/IOlPVWtU+1xT4sM=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
d4CKqie==
</ds:SignatureValue>
<ds:KeyInfo Id="KI-9A8D1F611E86CFB79E144316684667546">
<wsse:SecurityTokenReference oas:Id="STR-9A8D1F611E86CFB79E144316684667547">
<wsse:KeyIdentifier EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3">5lAB5TaqeFwo23mRVm31LngBT1dQMf94mxeVkyKog==
</wsse:KeyIdentifier>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
<oas:Timestamp oas:Id="TS-30">
<oas:Created>2015-09-25T07:40:46.670Z</oas:Created>
<oas:Expires>2015-09-26T11:27:26.670Z</oas:Expires>
</oas:Timestamp>
</wsse:Security>
</soapenv:Header>
<soapenv:Body oas:Id="id-31">
...
</soapenv:Body>
</soapenv:Envelope>
In soapUI, under the "WS-Security Configurations" I added the Keystores (jks with my private cert) and Truststores (jks with CA root public key). Finally I added "Outgoing WS-Security Configurations" with the following setting.
With this WS-Security setting, the soap message adds the wsse:Security as shown above.
Now, we are building the WS client on the .NET with WCF, and need help with the Binding and Security settings. What binding and configuration settings can be used to have the same WS-Security header as required or shown above?
From the WSDL, I created a client-side proxy using WSCF.blue. Although, I could have also used svcutil.exe or using Add Service Reference from VS.
I have tried creating the customBinding in code as following, but when inspecting this message the wsse header is not the same as what I want.
For example, it adds a BinarySecurityToken in the Security header which is not desired.
Or the KeyIdentifier is X509SubjectKeyIdentifier instead of X509v3 for example:
<o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier" ...</o:KeyIdentifier>
It also adds additional multiple Reference under the SignedInfo, and even though it passes schema validation, I am not sure what the additional Reference is doing.
internal static Binding GetCustomBinding()
{
CustomBinding myBinding = new CustomBinding();
AsymmetricSecurityBindingElement asBindingElement = new AsymmetricSecurityBindingElement();
//Have tried these also
//asBindingElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12;
//asBindingElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
//WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10
asBindingElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10;
asBindingElement.InitiatorTokenParameters = new System.ServiceModel.Security.Tokens.X509SecurityTokenParameters { InclusionMode = SecurityTokenInclusionMode.Never };
asBindingElement.RecipientTokenParameters = new System.ServiceModel.Security.Tokens.X509SecurityTokenParameters
{
//X509ReferenceStyle = X509KeyIdentifierClauseType.SubjectKeyIdentifier,
InclusionMode = SecurityTokenInclusionMode.Never
};
asBindingElement.MessageProtectionOrder = System.ServiceModel.Security.MessageProtectionOrder.SignBeforeEncrypt;
//asBindingElement.SecurityHeaderLayout = SecurityHeaderLayout.Strict;
asBindingElement.SecurityHeaderLayout = SecurityHeaderLayout.LaxTimestampLast;
asBindingElement.EnableUnsecuredResponse = true;
asBindingElement.IncludeTimestamp = true;
asBindingElement.SetKeyDerivation(false);
asBindingElement.DefaultAlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic128Rsa15;
asBindingElement.EndpointSupportingTokenParameters.Signed.Add(new X509SecurityTokenParameters());
myBinding.Elements.Add(asBindingElement);
myBinding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
//myBinding.Elements.Add(new MtomMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
HttpsTransportBindingElement httpsBindingElement = new HttpsTransportBindingElement();
httpsBindingElement.RequireClientCertificate = true;
myBinding.Elements.Add(httpsBindingElement);
return myBinding;
}
Additionally, I am using this behaviour for the x509 cert
<behaviors>
<endpointBehaviors>
<behavior name="MyBehavior">
<clientCredentials>
<clientCertificate findValue="xxx"
storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
<serviceCertificate>
<defaultCertificate findValue="xxx"
storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
<authentication certificateValidationMode="None" revocationMode="NoCheck"
trustedStoreLocation="LocalMachine" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
If you want to send the exact same message than you should probably use the SignedXml class to generate the signature outside of WCF. With WCF you will not be able to get the exact canonicalization algorithn / InclusiveNamespace.
Having said that most of the time producing a similar message is fine with the server. You have two possible approaches. One is to create a customMessageEncoder which will change the outgoing WCF message before it hits the network. So you can tell WCF to create a minimalist message (e.g. no timestamp) and in the encoder add the timestamp yourself (if wcf would create it then it would also sign it) and also remove/change the x.509 token references. You should be careful not to change any signed xml nodes when doing do (body, signedInfo) including whitespaces (so use preserveWhitepsaces if loading to XmlDocument).
Another approach is to try and configure WCF to send the same message:
to exclude the extra token reference create the x.509 params like this:
X509SecurityTokenParameters x509Params = new X509SecurityTokenParameters();
x509Params.X509ReferenceStyle =
X509KeyIdentifierClauseType.SubjectKeyIdentifier;
x509Params.RequireDerivedKeys = false;
;
x509Params.InclusionMode = SecurityTokenInclusionMode.Never;
x509Params.ReferenceStyle = SecurityTokenReferenceStyle.Internal;
x509Params.X509ReferenceStyle = X509KeyIdentifierClauseType.Any;
((AsymmetricSecurityBindingElement) sec).InitiatorTokenParameters = x509Params;
timestamp will be signed by wcf, but possibly the server does not care, or does not require a timestamp, so try requireTimestamp=true/false and see what works. You might be able to programatically disable signing for timestamps by using MessagePartSpecification.
The important in either approach is to understand the server might be more flexible than you think and to understand from its error messages what are the real show stoppers.

WCF Client for Axis2/Rampart Webservice using WS security without client certificate

I´m just facing some problems setting up a WCF(.NET 4.0) webservice to call an Axis2 Rampart webservice.
I´m new to WCF and i didn´t find a tutorial wich completly fits this special scenario.
Here are the facts:
The webservice i have to call is an Axis2 Ramart service.
The Client i need to build uses WCF/.NET 4.0.
The Webservice uses SOAP 1.1 and WS-Security (Messagesecurity).
WS-Securtity should work like this:
The server provides a certificate with the public key.
The client generates a secret symmetric key.
The client encrypts this secret key with the servers public key.
This encrypted key is written into the Soap-header.
The client encrypts the body of the Soap request with the secret key.
(In fact the dodumentation I got from the webservice provider says that the body is encrypted with the servers public key, but in the sample request they provide, the encryption method is stated as aes128-cbc wich is a symmetric key AFAIK)
So this is what i have to do.
What i have done so far was to try some custom bindings from several tutorials.
But all samples I found uses server AND CLIENT-certificates and I didn´t managed to adjust these bindings in a way that works for me.
So here is a sample-request that shows how the request should look like:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
<xenc:EncryptedKey Id="EncKeyId-Cl6B57CC684EEpm8E6E61WBp3421878712">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<wsse:SecurityTokenReference>
<wsse:KeyIdentifier EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#ThumbprintSHA1">D99lKi5jizWOxThG6yZXw6llwq4FdM=</wsse:KeyIdentifier>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>Ab5i63RFNPNXcoEn6PqflaoPjsUI3E5EZh668621xkMcEDz9Jcm204A5Ecn8WQamxKX7UYEG8gPwn66X+pOj0DiWD4ShKVJIOD5gCliobcGgjVB1Uihj8Xk5MGesi8atuy9RFA=</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedKey>
<wsc:DerivedKeyToken xmlns:wsc="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="derivedKeyId-1">
<wsse:SecurityTokenReference>
<wsse:Reference URI="#EncKeyId-Cl6B57CC684EEpm8E6E61WBp3421878712"
ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKey" />
</wsse:SecurityTokenReference>
<wsc:Offset>0</wsc:Offset>
<wsc:Length>16</wsc:Length>
<wsc:Nonce>wQ9oyLHKjKRx6Dlm04RaL5Q==</wsc:Nonce>
</wsc:DerivedKeyToken>
<xenc:ReferenceList>
<xenc:DataReference URI="#EncDataId-2" />
</xenc:ReferenceList>
</wsse:Security>
</soapenv:Header>
<soapenv:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Id-15079889">
<xenc:EncryptedData Id="EncDataId-2" Type="http://www.w3.org/2001/04/xmlenc#Content">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:Reference URI="#derivedKeyId-1" />
</wsse:SecurityTokenReference>
</ds:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>
+Tx9+XL7QqFVZKCr5wEhyOBENlCfHm0y1y5yWwnIk2kHNoO3IFFJj2rSQdt7HiqfcU6XxAVn3eVJKmmuN+rPYISoJstl8EnStaEIqSTuUyTUrgchx5Zxor47TOknXXjo3dYhTKHqvsx8SX70GG3M+bJS/Q1CWDlWzidKWxORo8D02iVcQdu00dnw7SHWYwyzzhduQbsozyzcAER5cYnQuuUPOcBusivq/L0xDOVTFaGr9/vvPGo+yk2bN0nBLeikk0uSJr7Z/IqGL+Dqg5BA0f+8X8sxFQpRQmtSoXtvhs2bGy8v1MPkCYKPmajSR/XwMaQB2zxR6vKsGA7ODH9+ocqO+rbPOYWpRz+czogOUo5s+OYIwX9u+99NmC5zuSjvK5bwJzWWrJ0h31OM0KeTkc7rxTIm8QMR5ytBNnCtU9QXQeAMbBdwGok330rq5ZH9bN4TdBg9Qhzs8CGGpjMYZaQ9ApTt6vkGK0i9gtdXdvY1fVZpsPcU67MYvkXJARQMpwj9Z3ZDVscdiPIxvfHyBkT8Ta21mDlYRidxanr87CrLB6HyiEyhD1XKwpTZ7OpNja6UOzfGNOJx07SbgGF+ozDBaC7zs691L4iawDioXagUZSkQ9UgwaqycSh3YYa5+RYuPka1Z0z2cmdAaFnEtoZAaSftGj8k=
</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</soapenv:Body>
</soapenv:Envelope>
Perhaps someone could tell me how I can accomplish this, or where I can find some tutorials.
Thank you in advance.
This is the Resposne I get after I´ve implementet the Custom Binding and the Messsage-Encoder:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
<wsc:DerivedKeyToken xmlns:wsc="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="derivedKeyId-159">
<wsse:SecurityTokenReference>
<wsse:KeyIdentifier EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKeySHA1">Aef7igYIlyWYa9XrbSYSt9Lh5Q4=</wsse:KeyIdentifier>
</wsse:SecurityTokenReference>
<wsc:Offset>0</wsc:Offset>
<wsc:Length>16</wsc:Length>
<wsc:Nonce>Ub30ogcNT6p7ZkH+qXFclw==</wsc:Nonce>
</wsc:DerivedKeyToken>
<wsc:DerivedKeyToken xmlns:wsc="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="derivedKeyId-159">
<wsse:SecurityTokenReference>
<wsse:KeyIdentifier EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKeySHA1">">Aef7igYIlyWYa9XrbSYSt9Lh5Q4=</wsse:KeyIdentifier>
</wsse:SecurityTokenReference>
<wsc:Offset>0</wsc:Offset>
<wsc:Length>16</wsc:Length>
<wsc:Nonce>Ub30ogcNT6p7ZkH+qXFclw==</wsc:Nonce>
</wsc:DerivedKeyToken>
<xenc:ReferenceList xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:DataReference URI="#EncDataId-160"/>
</xenc:ReferenceList>
</wsse:Security>
</soapenv:Header>
<soapenv:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Id-1046510178">
<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="EncDataId-160" Type="http://www.w3.org/2001/04/xmlenc#Content">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:Reference URI="#derivedKeyId-159"/>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>zQUBHBX2nMTfL5gxXseNqqE5goAFSPQEd2D1RAsUZi+L64gqYfdQQIg//hWhw0Ed9gGFxLX8/ocq
svVX7oVTN4YkCF9LdLmY1y7/SmbDMyjKjzhxvQ5Bz2mu1EzWBtWRjAYGnMtLTJCCWEK0ZeqKGXDi
rqcHMwJYK4vGKeizAl/BMN2dLqp4gANSHB7kryGYiK4C2NncYwpbbws/It6Lm2RPuUenFW+2VCaC
OW8YdCMMfveEvO+18+BaApxS2ShckTbip9nbpDzVvGw4gFw/70xAupMkkUEGJPdBnb6ce9qC/jQm
MeBL4FSenEJbqR1qSU5xh6rD7m6Vqug5mEP7c2Tk/mPSFVlZ88TXV2S31NB+3PDAXxyZss9aftBl
L+q+m8oP/hqse9Oju8MaztP/gBQDSKuTBLWgMPvwluEZmnPnpItZX9CFOVGDaaWlnoN1Lgc6iKk/
8xDC95t87++NesK6Zqa+J15qGm4MozFBe5pS75wARrGA34USnHytNNJGyidx15wQgNrT9gxTlypQ
BU3830rWiWAsrFwzSQBC20TcNb0ofscNJqVhwmRnMHz75Gbn70jyGTM0W27PFYfq/xfJ3MCe/pov
Dqn647j2Ixvj/Rik02HJdUUm/cdmRxawWQVUvmxPbPNNOjCoccwOWxf623zXpD3DdV8U/5+jDite
eQnrpaU4griXc7jq85OIoghf++cShAK+tx5t8BjLaD1rBF3ni5Eqt2xbMoZ6cfzr314PxmffyjHM
rCzSMU4cw0BndzJrV2r0aKTEPxVRPIQur8ztEtIYCRWloceS4N2YKkdRm/W7TWBsIa+HOCpq9Rpr
bu0KLP54tBBTO5hzjIsjYn7JzfohYk5aDN/8ZsQqgsO0LhWu/9qj8j2fY+yC4W9i7m+/bLvuYSbO
Tm7B0vV5s79uG4Xi/ONM7O1NR/C1HSEddQnr0/zdDxJcJsxwAmyryILmLynaZyxeFYz5ueqQuNCZ
MTRvKdEfw2+Tt7l3lUSZ/WqPcAz2UFA7kdASk2esmQjVZjvvdLQfan7xHffU1Ga5nmafuXrCZR81
k+1OYs64oy14qFor0e3DXlyeUOPC67iEP92lBQl7hz4v9I0afSmEhmc3iR/XoYTgliP2QhkeEw11
gSGa9u6oLfQfGZVsDV6meL51kkM+FRKq8Y2QjJjSyVFUzQXmg0lAySjlTjVeYZbRCSleCSqk+tIJ
XIcsdkY9PSVxdWOiqXQcQlrae1Wj34Xf+h6NpNuIt/TSKxd896b0ACzz8ouHUvI/Wyk5Rz/Rmvzi
g/cGK9YnX8VGV2hpUzsVZLByUoWvMH+hv9ep1syQiA5EiIu+paTS92CW1i2x39pnKeMrYhI6Ug==</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</soapenv:Body>
</soapenv:Envelope>
And This is the ReadMessage-Function of My MessageEncoder (I know it´s not the best way to parse Xml). It removes one of the two derived keys:
public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
{
var msg = innerEncoder.ReadMessage(buffer, bufferManager, contentType);
var xml = msg.ToString();
var msgbuffer = msg.CreateBufferedCopy( int.MaxValue );
msg = msgbuffer.CreateMessage();
MemoryStream stream = new MemoryStream();
XmlDictionaryWriter xmlWriter = XmlDictionaryWriter.CreateBinaryWriter(stream);
msg.WriteMessage(xmlWriter);
xmlWriter.Flush();
stream.Position = 0;
XmlDictionaryReader xmlReader = XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max);
XmlDocument doc = new XmlDocument();
doc.Load(xmlReader);
XmlNode security = null;
XmlNode derivdeKey = null;
foreach (XmlNode xnode in doc.DocumentElement.FirstChild.ChildNodes)
{
if (xnode.LocalName == "Security")
foreach (XmlNode node in xnode.ChildNodes)
{
security = node;
if(node.LocalName == "DerivedKeyToken")
{
}
if(derivdeKey != null)
{
XmlNode pnode = node.ParentNode;
pnode.RemoveChild( node );
}
else
{
derivdeKey = node;
}
}
}
Stream memStream = new MemoryStream();
xmlWriter = XmlDictionaryWriter.CreateBinaryWriter( memStream );
doc.WriteTo(xmlWriter);
xmlWriter.Flush();
memStream.Position = 0;
xmlReader = XmlDictionaryReader.CreateBinaryReader(memStream, XmlDictionaryReaderQuotas.Max);
Message newMessage = Message.CreateMessage(xmlReader, 10240, msg.Version);
xml = newMessage.ToString();
return newMessage;
}
I`m wondering about how the Message is shown as string (newMessage.ToString()) because the body is shon was ...stream....
The Problem is that I get the followingError-message:
System.ServiceModel.Security.MessageSecurityException : The 'Body', 'http://schemas.xmlsoap.org/soap/envelope/' required message part was not signed.
So I stripped of the Security node as descriped here http://webservices20.blogspot.de/2012/04/when-enableunsecuredrespose-requires.html.
This is the stripped resonse:
<?xml version="1.0" encoding="utf-16"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body wsu:Id="Id-1532543044" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><xenc:EncryptedData Id="EncDataId-586" Type="http://www.w3.org/2001/04/xmlenc#Content" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"><xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"></xenc:EncryptionMethod><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:Reference URI="#derivedKeyId-585"></wsse:Reference></wsse:SecurityTokenReference>
</ds:KeyInfo><xenc:CipherData><xenc:CipherValue>APZ9aATpcMu5qU6PdoKeTLjAblJP/uLZAzX8imgSSfvaZGGeI8prg9JNTEOjZ1SAeuWxod/ZV4pb
3OeY3b1IWxxhG5WWGxu51WAAehGBmiyFYOzJwbpR5cOHUc7aRBm7hkeqr/1RlcYDlAk4Y+G1URgv
0K2nzqfDR3m7ydZSVoa3aSWWzmhjMTnJnPyQ060fDXiU7/k0tI12danfv+tUcBAlvfssTTEB33bH
RXTjobJDuW3lEbbQBN+KD9SUu02GvFF4Vs31pSf1YxHIzMuf3Q2njz58oY0kmDRvR6+n9IIUQVgK
5+iJOx9E5pY7xzmEf5LpbiTt2RSuxmt2+nkin+wxF94hkgW/N6TwmbbjybN2TY3IyZ2PgdzobCj9
sG9UAwAE1peDvIpiXhgXyojU7eRnAfJKE4HrxEjs9GKdgA4SG3rsM7t/JAeiThqe4GZCvrKwnTHS
OZSz8wplTEV7VfALj5TvwK8DqOP4Qsk1F6pml/IQg0YSUJGQmuxZzTiM3ABRzf21/BUj9j3mlo7R
/QFhNnEAhHTLoJIW1fhKYrhT7vk6rMLlZtP7iyE63MEp4cghvSk9OZDauUBoUAkKwv9N2TSOBe3W
N0fVIpLg+gNmu8s1Myzl9MEDpqQFvJbG2+hTjREo9cyvfJdKLjZVpWVoaaghiZrOFwUWJsIGCyuy
aW+eF1wFP6WgXixmvX/mdkEqCyU29+DAlIb5yIABgIxNk4MSJP/9+cSZ7L6EOVJc9khsMgw1aGe9
k3QbIeM7WLXcHNnWFE+PuqORg7OvvG+jqFGyfGlGaE85lbD2+0ONTmxU3MwNhg9ngZLheiIzxxty
3R2KXDMkDEQpWJ7cIi2QSvwu0XZ/Ku5hwW8fXbUgHTClpAQbwu3HqeeHv2BkhrUbPbx3pRpu6B4L
tyGO4vfp/vlnPyT0xS5O99KX6iKpDDS3zqC9j0cheJIqIvixNvrLd/KrpQJ8nc7+B/29h444y/3I
jooRtDmtNuG2T3b4QB2oec7FS+ufXUJIEgPWtE6iPMZxMqiL1z64eL0sg2xO4QXWwoGzMCZHP89y
ibhjhsKDTffz/s4cgRgzRWAQSNlLpuvzDeHjbNUnXIz3C1NnQOBV0LF5KpCuyYeIfQDbJQpyTre1
q5KMTGHq4ksG2zSpgNNouS279WmlGOmuawLW28VxRBlW92K//l16yJglEcKbqlRuxzM0gcw1BG/O
9sp25te+Ad68Vo2dyELZYstIRhSnV2j2J6UyZd1WC1rBWHiu3gDvKgeCNtgUbeHKfm0RVo9ZBVbi
vHQWAL57hOBERoXK5MkhwqlsYZzOHzkoVyxok+UspcmVy1MQccOcB6y5xbuqt6zR+iFuKyZVGQ==</xenc:CipherValue></xenc:CipherData></xenc:EncryptedData></soapenv:Body></soapenv:Envelope>
Now the Service finishes without errors, but the result-object is null.
-> example:
result = testserviceproxy.testservicefunction();
result is null;
This binding is the closest you could get with ootb wcf:
<customBinding>
<binding name="NewBinding0">
<textMessageEncoding messageVersion="Soap11" />
<security defaultAlgorithmSuite="Basic128Rsa15" authenticationMode="AnonymousForCertificate"
includeTimestamp="false" messageProtectionOrder="EncryptBeforeSign">
<secureConversationBootstrap />
</security>
<httpTransport />
</binding>
</customBinding>
It produces a very similar XML with one different: It also adds a digital signature. There is no way to directly tell WCF not to add a signature. Most chances are this will not be a problem for you to send the message as is (with signature). If this is a problem you could implement a WCF custom message encoder to manually remove the signature element (and also the one out of two derived keys which is used specifically for signature).

Wcf Backward compatibility issue - missing namespace on method parameter

we are hosted our WCF web service in windows service. We are using basicHttpBinding. We need preserve backward compatibility with Soap 1.1 Web service. Our problem is missing namespace on element EPTalkMessage in web method parameter. I searched a lot but I didn't find some way to add namespace to this element.
Soap from old web service is:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://aaa.sk/EPTalk/IssueDocument</Action>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<IssueDocument xmlns="http://aaa.sk/EPTalk">
<EPTalkMessage xmlns="http://aaa.sk/EPTalk/ToSignInput" />
</IssueDocument>
</s:Body>
</s:Envelope>
New generated soap is:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://aaa.sk/EPTalk/IssueDocument</Action>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<IssueDocument xmlns="http://aaa.sk/EPTalk">
<EPTalkMessage />
</IssueDocument >
</s:Body>
</s:Envelope>
Service signature is as follows:
[ServiceContract (Namespace = "http://aaa.sk/EPTalk")]
[XmlSerializerFormat(Use = OperationFormatUse.Literal, Style = OperationFormatStyle.Document)]
public interface IRegistryInputWebService
{
[OperationContract(Action = "http://aaa.sk/EPTalk/IssueDocument")]
RegistryServiceResult IssueDocument([MessageParameter(Name = "EPTalkMessage")]
UpvsPortalEmulator.ToSignInput.EPTalkMessage message);
}
Binding:
BasicHttpBinding
{
MaxReceivedMessageSize = 1024 * 1024 * 10,
MaxBufferSize = 1024 * 1024 * 10,
ReaderQuotas =
{
MaxArrayLength = 1024 * 1024 * 10,
MaxStringContentLength = 1024 * 1024 * 10
},
MessageEncoding = WSMessageEncoding.Text,
Security = new BasicHttpSecurity
{
Mode = BasicHttpSecurityMode.None
}
};
Edited: EPTalkMessage definition added.
[XmlType, XmlRoot (ElementName = "EPTalkMessage", Namespace = Declarations.SchemaVersion, IsNullable = false), Serializable]
public class EPTalkMessage
{
}
Thanks a lot for your help
After searching for a while, I resolved this issue with MessageContracts.