C# WCF Client Binding Interop Blackboard Java WS-Security over HTTPS Transport -
i having trouble getting wcf binding work blackboard java web services api.
(simple answer if has got working please post working binding wcf blackboard)
i have spent hours trying different configurations , custom coded bindings.
some unsuccessful attempts:
calling-a-ws-security-java-web-service-with-c-sharp-client
wcf-client-with-ws-security 12-common-wcf-interop-confusions
configure-wcf-for-ws-security-with-username-over-https
wcf-client-connecting-to-java-soap-web-service-using-ws-security
clearusernamebinding
there many more java , ws-security wcf wont go on.
it seems every time 1 thing working breaks. feel going around in circles , making myself more confused.
as first test trying simple initialize context object , login using admin test user account wcf proxy.
blackboard doc contextws
to make sure of worked first downloaded sample code .net wse 2.0 , tested that, worked perfectly.
now when use wcf , binding cannot same behaviour.
first successful exchange old wse 2.0 ===================================
wse 2.0 contextws initialization
<?xml version="1.0" encoding="utf-8"?> <soap:envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xsd="http://www.w3.org/2001/xmlschema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" 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"> <soap:header> <wsa:action>initialize</wsa:action> <wsa:messageid>uuid:b975e989-a4ce-4e1e-abd6-500945346c40</wsa:messageid> <wsa:replyto> <wsa:address>http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous</wsa:address> </wsa:replyto> <wsa:to>https://blackboard.server.name/webapps/ws/services/context.ws</wsa:to> <wsse:security soap:mustunderstand="1"> <wsu:timestamp wsu:id="timestamp-47d0d017-4fd1-46c2-b1b4-2431402cf847"> <wsu:created>2015-07-16t04:58:02z</wsu:created> <wsu:expires>2015-07-16t05:03:02z</wsu:expires> </wsu:timestamp> <wsse:usernametoken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:id="securitytoken-1b71e23a-2d84-40a5-9509-b75902ec8b76"> <wsse:username>session</wsse:username> <wsse:password type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#passwordtext">nosession</wsse:password> <wsse:nonce>law2qxrxz1mannkcezlhga==</wsse:nonce> <wsu:created>2015-07-16t04:58:02z</wsu:created> </wsse:usernametoken> </wsse:security> </soap:header> <soap:body /> </soap:envelope>
wse 2.0 contextws initialization success response
<?xml version='1.0' encoding='utf-8'?> <soapenv:envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:body> <ns:initializeresponse xmlns:ns="http://context.ws.blackboard"> <ns:return>c2762f357bbc42a4a88d33e4e42486b8</ns:return> </ns:initializeresponse> </soapenv:body> </soapenv:envelope>
wse 2.0 contextws login request
<?xml version="1.0" encoding="utf-8"?> <soap:envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xsd="http://www.w3.org/2001/xmlschema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" 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"> <soap:header> <wsa:action>login</wsa:action> <wsa:messageid>uuid:a823128b-efb4-49e1-87d9-fd35167f0bfc</wsa:messageid> <wsa:replyto> <wsa:address>http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous</wsa:address> </wsa:replyto> <wsa:to>https://blackboard.server.name/webapps/ws/services/context.ws</wsa:to> <wsse:security soap:mustunderstand="1"> <wsu:timestamp wsu:id="timestamp-c38daf19-6b39-4391-a3f8-bcc030064a3e"> <wsu:created>2015-07-16t04:58:15z</wsu:created> <wsu:expires>2015-07-16t05:03:15z</wsu:expires> </wsu:timestamp> <wsse:usernametoken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:id="securitytoken-65948746-e616-436a-85f4-d2e1023e39be"> <wsse:username>session</wsse:username> <wsse:password type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#passwordtext">c2762f357bbc42a4a88d33e4e42486b8</wsse:password> <wsse:nonce>t0xs8aiaiodmk3sfkgdqtg==</wsse:nonce> <wsu:created>2015-07-16t04:58:15z</wsu:created> </wsse:usernametoken> </wsse:security> </soap:header> <soap:body> <login xmlns="http://context.ws.blackboard"> <userid>test_admin</userid> <password>testpassword</password> <clientvendorid>testclient</clientvendorid> <clientprogramid>testpoc</clientprogramid> <loginextrainfo xsi:nil="true" /> <expectedlifeseconds>10000000</expectedlifeseconds> </login> </soap:body> </soap:envelope>
wse 2.0 contextws login success response
<?xml version='1.0' encoding='utf-8'?> <soapenv:envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:body> <ns:loginresponse xmlns:ns="http://context.ws.blackboard"> <ns:return>true</ns:return> </ns:loginresponse> </soapenv:body> </soapenv:envelope>
===================================
so know works our environment , know user can login.
using wcf able initialization working looses session. not put returned session id password field next message. have tried manually of course; error stating password field read only.
now wcf configuration , code has gotten me closest above communication.
wcf app.config binding
<?xml version="1.0" encoding="utf-8" ?> <configuration> </system.servicemodel> <bindings> <custombinding> <binding name="wcfsoapinteropjavaws" closetimeout="00:01:00" opentimeout="00:01:00" receivetimeout="00:10:00" sendtimeout="00:01:00" > <textmessageencoding messageversion="soap11" writeencoding="utf-8" /> <security authenticationmode="usernameovertransport" enableunsecuredresponse="true" allowserializedsigningtokenonreply="true" messagesecurityversion="wssecurity10wstrustfebruary2005wssecureconversationfebruary2005wssecuritypolicy11basicsecurityprofile10" includetimestamp="true" allowinsecuretransport="true" canrenewsecuritycontexttoken="false" > </security> <httpstransport authenticationscheme="anonymous" /> </binding> </custombinding> </bindings> <client> <endpoint address="https://blackboard.server.name:443/webapps/ws/services/context.ws" binding="custombinding" bindingconfiguration="wcfsoapinteropjavaws" contract="contextws.contextwsporttype" name="context.wcfsoapinteropjavaws" /> </client> </system.servicemodel> </configuration>
wcf c# code
public bool testwrapper(string userid, string userpassword){ try { context = new contextwrapper("context.wcfsoapinteropjavaws"); context.clientcredentials.username.username = "session"; context.clientcredentials.username.password = "nosession"; context.initialize(); //context.clientcredentials.username.password = "886d935527944f94a3526288e39a555e"; // sessionguid_here throws read error pasword bool retval = context.login(userid, userpassword, vendorid, programid, null, expectedlife); return retval; } catch (system.exception e) { lasterror = e; return false; } }
this soap communication looks like.
wcf contextws initialization request
<s:envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <s:header> <vsdebuggercausalitydata xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uidpo+fmveflwutmgsatru3ht9eaaaaamyvjsx+bhueyctdsfqfktkqe8xmmia1mpxouaouxgjwacqaa</vsdebuggercausalitydata> <o:security s:mustunderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <u:timestamp u:id="_0"> <u:created>2015-07-16t07:15:05.109z</u:created> <u:expires>2015-07-16t07:20:05.109z</u:expires> </u:timestamp> <o:usernametoken u:id="uuid-1237f56c-7c68-4d40-a756-7ff2c19a3235-1"> <o:username>session</o:username> <o:password type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#passwordtext">nosession</o:password> </o:usernametoken> </o:security> </s:header> <s:body xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xsd="http://www.w3.org/2001/xmlschema"/> </s:envelope>
wcf contextws initialization success response
<?xml version='1.0' encoding='utf-8'?> <soapenv:envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:body> <ns:initializeresponse xmlns:ns="http://context.ws.blackboard"> <ns:return>886d935527944f94a3526288e39a555e</ns:return> </ns:initializeresponse> </soapenv:body> </soapenv:envelope>
wcf contextws login request
<s:envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <s:header> <vsdebuggercausalitydata xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uidpo+jmveflwutmgsatru3ht9eaaaaamyvjsx+bhueyctdsfqfktkqe8xmmia1mpxouaouxgjwacqaa</vsdebuggercausalitydata> <o:security s:mustunderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <u:timestamp u:id="_0"> <u:created>2015-07-16t07:15:14.033z</u:created> <u:expires>2015-07-16t07:20:14.033z</u:expires> </u:timestamp> <o:usernametoken u:id="uuid-1237f56c-7c68-4d40-a756-7ff2c19a3235-1"> <o:username>session</o:username> <o:password type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#passwordtext">nosession</o:password> </o:usernametoken> </o:security> </s:header> <s:body xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xsd="http://www.w3.org/2001/xmlschema"> <login xmlns="http://context.ws.blackboard"> <userid>test_admin</userid> <password>testpassword</password> <clientvendorid>testclient</clientvendorid> <clientprogramid>testpoc</clientprogramid> <loginextrainfo xsi:nil="true"/> <expectedlifeseconds>10000000</expectedlifeseconds> </login> </s:body> </s:envelope>
wcf contextws login failed response
<?xml version='1.0' encoding='utf-8'?> <soapenv:envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:body> <soapenv:fault> <faultcode>soapenv:server</faultcode> <faultstring>[wsfw001]invalid session</faultstring> <detail /> </soapenv:fault> </soapenv:body> </soapenv:envelope>
as can see session return id has not been added password field on login request there "invalid session:
it seemed going well.
in short if knows how achieve binding wcf client blackboard java webservice api , example fantastic. other wise hoping else knows more wcf bindings java might able take @ above see going wrong.
any can give me working appreciated thanks. hoping silly missing.
sorry such long detailed question.
thanks heaps of reading , useful samples able working. blackboard wcf.
thanks go both: ajadex lopez
http://www.isyourcode.com/2010/08/attaching-oasis-username-tokens-headers.html
johnny lockhart "incoming message not contain required security header"
bb buggie might best search forum wcf find post
sample class
using system; using system.servicemodel.description; using system.servicemodel.channels; using system.servicemodel.dispatcher; using system.servicemodel; using system.xml; using system.security.cryptography; using system.text; namespace bbwcfwrapper { /// <summary> /// coupled additional classes below, allows injecting ws-security header wcf service call without requiring ssl on server. /// </summary> /// <remarks>http://isyourcode.blogspot.com/2010/08/attaching-oasis-username-tokens-headers.html</remarks> public class bbwssecuritybehavior : iendpointbehavior { public messageinspector messageinspector { get; set; } public bbwssecuritybehavior(messageinspector messageinspector) { messageinspector = messageinspector; } public void validate(serviceendpoint endpoint) { } public void addbindingparameters(serviceendpoint endpoint, bindingparametercollection bindingparameters) { } public void applydispatchbehavior(serviceendpoint endpoint, endpointdispatcher endpointdispatcher) { } public void applyclientbehavior(serviceendpoint endpoint, clientruntime clientruntime) { if (this.messageinspector == null) throw new invalidoperationexception("caller must supply clientinspector."); clientruntime.messageinspectors.add(messageinspector); } } public class messageinspector : iclientmessageinspector { public messageheader[] headers { get; set; } public messageinspector(params messageheader[] headers) { headers = headers; } public object beforesendrequest(ref message request, iclientchannel channel) { if (headers != null) { (int = headers.length - 1; >= 0; i--) { request.headers.insert(0, headers[i]); } } return request; } public void afterreceivereply(ref message reply, object correlationstate) { } } public class securityheader : messageheader { public string systemuser { get; set; } public string systempassword { get; set; } public securityheader(string systemuser, string systempassword) { systemuser = systemuser; systempassword = systempassword; } public override string name { { return "security"; } } public override string namespace { { return "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; } } protected override void onwritestartheader(xmldictionarywriter writer, messageversion messageversion) { writer.writestartelement("wsse", name, namespace); writer.writexmlnsattribute("wsse", namespace); writer.writeattributestring("soap", "mustunderstand", namespace, "1"); } protected override void onwriteheadercontents(xmldictionarywriter writer, messageversion messageversion) { writeheader(writer); } private void writeheader(xmldictionarywriter writer) { var createdate = datetime.now; //start parent elements writer.writestartelement("wsu","timestamp","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); writer.writeattributestring("wsu","id","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd","timestamp-6557466"); #region start child elements writer.writestartelement("wsu", "created", xmlconvert.tostring(createdate, "yyyy-mm-ddthh:mm:sszzzzzz")); writer.writeendelement(); //end created writer.writestartelement("wsu", "expires", xmlconvert.tostring(createdate.adddays(1), "yyyy-mm-ddthh:mm:sszzzzzz")); writer.writeendelement(); //end expires #endregion writer.writeendelement(); //end timestamp //start parent elements writer.writestartelement("wsse", "usernametoken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); writer.writexmlnsattribute("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); #region start child elements writer.writestartelement("wsse", "username", null); writer.writestring(systemuser); writer.writeendelement();//end username writer.writestartelement("wsse", "password", null); writer.writeattributestring("type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#passwordtext"); writer.writestring(systempassword); writer.writeendelement();//end password // unique nonce value - encode sha-1 'randomness' // in theory nonce guid // used stop replay attacks writer.writestartelement("wsse", "nonce", null); writer.writestring(getsha1string(guid.newguid().tostring())); writer.writeendelement();//nonce writer.writestartelement("wsu", "created", null); writer.writestring(xmlconvert.tostring(createdate, "yyyy-mm-ddthh:mm:sszzzzzz")); writer.writeendelement(); //end created #endregion writer.writeendelement();//end usernametoken writer.flush(); } protected string getsha1string(string phrase) { sha1cryptoserviceprovider sha1hasher = new sha1cryptoserviceprovider(); byte[] hasheddatabytes = sha1hasher.computehash(encoding.utf8.getbytes(phrase)); return convert.tobase64string(hasheddatabytes); } } }
example use
calendar = new calendarwrapper("calendar.bb_wssecurity_binding"); //this adds custom security headder wcf , java ws-security interop calendar.endpoint.behaviors.add(new bbwssecuritybehavior(new messageinspector(bbwsauth.securityheader))); calendar.initializecalendarws(false);
simple wrapper class
public class calendarwrapper : calendarwsporttypeclient { public calendarwrapper() : base() { } public calendarwrapper(string endpointconfigurationname) : base(endpointconfigurationname) { } public calendarwrapper(binding binding, endpointaddress remoteaddress) : base(binding, remoteaddress) { } }
config
<bindings> <basichttpsbinding> <binding name="bb_wssecurity_binding" messageencoding="text" textencoding="utf-8" maxreceivedmessagesize="4000000" > <readerquotas maxdepth="32" maxstringcontentlength="8192" maxarraylength="16384" maxbytesperread="4096" maxnametablecharcount="16384" /> </binding> </basichttpsbinding> </bindings> <client> <endpoint address="https://xxxxxxxxxx/webapps/ws/services/calendar.ws" binding="basichttpsbinding" bindingconfiguration="bb_wssecurity_binding" contract="calendarws.calendarwsporttype" name="calendar.bb_wssecurity_binding" />
Comments
Post a Comment