c# - Correct way communicate WSSE Usernametoken for SOAP webservice -


i attempting consume web service through corresponding wsdl. service dependent upon authentication conforming web services security basic security profile 1.0 including correct xmls namespace of http://docs.oasis-open.org/wss/2004/01/oasis-200401wss-wssecurity-secext-1.0.xsd must included in request.

example:

<wsse:usernametoken xmlns:wsse='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' >    <wsse:username>       bob    </wsse:username>    <wsse:password type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#passwordtext'>       1234    </wsse:password> </wsse:usernametoken> 

my first attempts along lines of add service reference targeting wsdl , generated proxies using them such

servicepointmanager.servercertificatevalidationcallback =      (object s, x509certificate certificate, x509chain chain,                      sslpolicyerrors sslpolicyerrors) => true;  var basichttpbinding = new basichttpbinding(basichttpsecuritymode.transport); basichttpbinding.security.transport.clientcredentialtype =                                                  httpclientcredentialtype.basic;  var endpoint = new endpointaddress("https://secure-ausomxana.crmondemand.com/..."  using (var client = new contactclient(basichttpbinding, endpoint)) {      var credential = client.clientcredentials.username;     credential.username = "bob";     credential.password = "1234";      var input = ...         var output = client.contactquerypage(input); } 

however attempting interrogate soap messages fiddler see no usernametoken element has been added.

what correct way fulfill contract?

edit: following response @john saunders attempted alter code use wshttpbinding

var wshttpbinding = new wshttpbinding(securitymode.transport); wshttpbinding.security.transport.clientcredentialtype =                                          httpclientcredentialtype.basic; 

using binding soap message becomes

<s:envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">   <s:header>     <a:action s:mustunderstand="1">document/urn:crmondemand/ws/ecbs/contact/10/2004:contactquerypage</a:action>     <a:messageid>urn:uuid:17807f44-1fcasfdsfd</a:messageid>     <a:replyto>       <a:address>http://www.w3.org/2005/08/addressing/anonymous</a:address>     </a:replyto>     <a:to s:mustunderstand="1">https://secure-ausomxana.crmondemand.com/services/integration</a:to>   </s:header>   <s:body xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xsd="http://www.w3.org/2001/xmlschema">     <contactquerypage_input xmlns="urn:crmondemand/ws/ecbs/contact/10/2004">       <listofcontact xmlns="urn:/crmondemand/xml/contact/query">         <contact>           <id>1-asdfd</id>         </contact>       </listofcontact>     </contactquerypage_input>   </s:body> </s:envelope> 

this adds header element, opposed wsse:usernametoken element reference original soap message using basichttpbinding is

<s:envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">   <s:body xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xsd="http://www.w3.org/2001/xmlschema">     <contactquerypage_input xmlns="urn:crmondemand/ws/ecbs/contact/10/2004">       <listofcontact xmlns="urn:/crmondemand/xml/contact/query">         <contact>           <id>1-asdfds</id>         </contact>       </listofcontact>     </contactquerypage_input>   </s:body> </s:envelope> 

if change binding

var wshttpbinding = new wshttpbinding(securitymode.transportwithmessagecredential); wshttpbinding.security.transport.clientcredentialtype = httpclientcredentialtype.basic; wshttpbinding.security.message.clientcredentialtype = messagecredentialtype.username; 

the soap message out is

<s:envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">   <s:header>     <a:action s:mustunderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/rst/sct</a:action>     <a:messageid>urn:uuid:eeb75457-f29e-4c65-b4bf-b580da26e0c5</a:messageid>     <a:replyto>       <a:address>http://www.w3.org/2005/08/addressing/anonymous</a:address>     </a:replyto>     <a:to s:mustunderstand="1">https://secure-ausomxana.crmondemand.com/services/integration</a:to>     <o:security xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" s:mustunderstand="1">       <u:timestamp u:id="_0">         <u:created>2011-05-02t13:30:09.360z</u:created>         <u:expires>2011-05-02t13:35:09.360z</u:expires>       </u:timestamp>       <o:usernametoken u:id="uuid-dc3605a0-6878-42f4-b1f2-37d5c04ed7b4-2">         <o:username>bob</o:username>         <o:password type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#passwordtext">1234</o:password>       </o:usernametoken>     </o:security>   </s:header>   <s:body>     <t:requestsecuritytoken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">       <t:tokentype>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</t:tokentype>       <t:requesttype>http://schemas.xmlsoap.org/ws/2005/02/trust/issue</t:requesttype>       <t:entropy>         <t:binarysecret u:id="uuid-7195ad74-580b-4e52-9e2c-682e5a684345-1" type="http://schemas.xmlsoap.org/ws/2005/02/trust/nonce">bi4xuykwz8okqybrnz2ldnv+zhionl0nwp24yi1qawa=</t:binarysecret>       </t:entropy>       <t:keysize>256</t:keysize>     </t:requestsecuritytoken>   </s:body> </s:envelope> 

this seems close appears have encrypted body of soap message not want happen.

if specify wshttpbinding.security.message.clientcredentialtype = messagecredentialtype.username; using securitymode.transport goes says anonymous.

what final hurdle i'm not able clear on this?

final solution: figured i'd post incase helps someone, there's not different here other usertoken object wrapped in security node service provider required , seems how output previous examples generated.

<system.servicemodel>   <bindings>         <basichttpbinding>       <binding name="contact" closetimeout="00:01:00" opentimeout="00:01:00"           receivetimeout="00:10:00" sendtimeout="00:01:00" allowcookies="false"           bypassproxyonlocal="false" hostnamecomparisonmode="strongwildcard"           maxbuffersize="524288" maxbufferpoolsize="524288" maxreceivedmessagesize="524288"           messageencoding="text" textencoding="utf-8" transfermode="buffered"           usedefaultwebproxy="true">         <readerquotas maxdepth="32" maxstringcontentlength="65536" maxarraylength="131072"             maxbytesperread="32768" maxnametablecharcount="131072" />         <security mode="transport">           <transport clientcredentialtype="none" proxycredentialtype="none"               realm="" />           <message clientcredentialtype="username" algorithmsuite="default" />         </security>       </binding>              </basichttpbinding>   </bindings>   <client>     <endpoint address="https://secure-ausomxana.crmondemand.com/services/integration"        binding="basichttpbinding" bindingconfiguration="contact"        contract="ondemandcontactservice.contact" name="ondemand.contact.endpoint">       <headers>                 <wsse:security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">           <wsse:usernametoken>             <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>       </headers>     </endpoint>   </client> </system.servicemodel> 

see with c#, wcf soap consumer uses wsse plain text authentication? how configure using code , not config

if need send username on https can use standard approach (if wsdl correctly defined should created automatically adding service reference):

<bindings>   <basichttpbinding>     <binding name="secured">       <security mode="transportwithmessagecredential">         <message clientcredentialtype="username" />       </security>     </binding>   </basichttpbinding> </bindings> <client>   <endpoint name="..." address="https://..." contract="..." binding="basichttpbinding"             bindingconfiguration="secured" /> </client> 

ar can define binding in code:

var basichttpbinding = new basichttpbinding(basichttpsecuritymode.transportwithmessagecredential); basichttpbinding.security.message.clientcredentialtype = basichttpmessagecredentialtype.username; 

you set credentials in proxy now:

client.clientcredentials.username.username = "bob"; client.clientcredentials.username.password = "1234"; 

if need usernametoken profile on http without other ws-security infrastructure simplest approach using clearusernamebinding.

if need same user name , password requests client can use simple basichttpbinding without security , include static header configuration:

<client>   <endpoint ...>     <headers>       <wsse:usernametoken xmlns:wsse='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' >         <wsse:username>bob</wsse:username>         <wsse:password type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#passwordtext'>            1234         </wsse:password>       </wsse:usernametoken>     </headers>   </endpoint> </client>  

if need more complex show relevant part of wsdl (security assertion) or sample soap request. mention if required use http or https.


Comments