Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

SOAP Toolkit and Secure Web Service Access


:P
On this page:

This is just an illustration just how badly designed the SOAP Toolkit was. I was working on my samples for Southwest Fox for my .NET Web Services Interop session from VFP. One of my samples demonstrates going out to my West Wind Web Store downloading a complex array of order business objects and then importing this data on the client.

 

I decided to use the SOAP Toolkit for demonstration purposes rather than my proprietary wwSOAP class, because in this case the data retrieved was actually in dataset format and the parsing wouldn’t be any easier with wwSOAP.

 

The code is straight forward if a little verbose, and it works just fine against my local machine. But when I tried to download orders off the Web from my live site the SOAP Toolkit choked. The live site uses authentication and sure enough I had to set authentication on the client. Setting authentication with the SOAP Toolkit involves setting a couple of connector properties which looks something like this:

 

PROTECTED FUNCTION SetMSSOAPConnectionProperties(lcUrl)

THIS.oSOAP = CREATEOBJECT(MSSOAP_PROGID)

      THIS.oSOAP.mssoapinit(lcUrl)


 
IF !EMPTY(THIS.cUserName)

          THIS.oSOAP.ConnectorProperty("AuthUser") = this.cUserName

          THIS.oSOAP.ConnectorProperty("AuthPassword") = this.cPassword

       ENDIF

       this.oSOAP.ConnectorProperty("ConnectTimeout") = this.nTimeout * 1000

       this.oSOAP.ConnectorProperty("Timeout") = this.nTimeout * 1000

 

       IF !EMPTY(THIS.cProxy)

          this.oSOAP.ConnectorProperty("ProxyServer") = this.cProxy

       ELSE

          this.oSOAP.ConnectorProperty("ProxyServer") = ""         

       ENDIF

ENDFUNC

 

Note the ever so intuitive use of Connector Properties, which are a lazy persons way of building a half assed tool kit.

 

But this still failed on the Web Service. Note that the ConnectorProperties can be set only AFTER the call to MsSoapInit(). See the problem here?

 

MsSoapInit() actually goes out and reads the WSDL file from the URL provided, but if the WSDL URL is also protected via Authentication, the MsSoapInit() call fails. Since in most applications – especially .NET Web Services – the Service Url and WSDL URL are one and the same physical page reference this is not going to work.

 

The workaround is a laughable one – you have to modify the WSDL URL by injecting the username and password into it in this format:

 

http://username:password@west-wind.com/webstore/service/AdminService.asmx?Wsdl

 

The code to inject this looks like this:
 

lcUrl = TRIM(this.cWSDLUrl)

 

*** Fix up Url to include username and password

*** How freaking lame is this???

IF !EMPTY(this.cUsername)

   lcUrl = STRTRAN(lcUrl,"http://","http://" + this.cUsername + ;

                   ":" + this.cPassword + "@",1,1,1)

   IF lcUrl = this.cWsdlUrl

      lcUrl = STRTRAN(this.cWSDLUrl,"https://","https://" + ;

                      this.cUsername + ":" + this.cPassword + "@",1,1,1)

    ENDIF

ENDIF


THIS
.oSOAP.mssoapinit(lcUrl)

 

Note that this URL isn’t a valid URL any longer as IE doesn’t allow username and password on the Address line in the browser. Why? Huge security risk to pass the username and password over the wire like this and the SOAP Toolkit happily goes ahead and sends it.

 

If you need proxy configuration on the WSDL URL – good luck. That feature cannot be embedded into the URL. I couldn’t find any info on getting that to work.

 

It’s a good thing that the SOAP Toolkit was a short lived thing for Microsoft with .NET Web Service clients superceding the functionality. The .NET client is much better but it too doesn’t have a lot of configurability. For example, native .NET does not have support for dynamically creating SOAP envelopes. That functionality was added only recently with WSE Service support and I presume Indigo (WCF) too will have that support buried somewhere in its bowels.

 

But SOAP for non-.NET clients is a pain in the ass. MSSOAP is full of holes, can’t deal with complex types. My own wwSOAP class (VFP based SOAP client) works for many things, but it doesn’t do nearly everything defined in the SOAP spec and it too chokes on off the wall SOAP implementations – it’s optimized for .NET and SOAP Toolkit Web Services. And even there, there are limitations.


The Voices of Reason


 

Brian Vander Plaats
October 10, 2005

# re: SOAP Toolkit and Secure Web Service Access

So are there any other options for VFP besides the soap toolkit or your wwSoap class? I've been playing with web services off and on for a year or so, and I've assummed that if the right application presents itself, I can implement the web service in .NET and access from FoxPro fairly simply. (I tried publishing a web service in FoxPro and it was't much fun) Doesn't sound like this is the case!

Rick Strahl
October 10, 2005

# re: SOAP Toolkit and Secure Web Service Access

Brian,

It depends on what you need to do. wwSOAP actually works pretty well with .NET Web Services, including reasonable support of complex objects. But it can't do somethings like returned arrays and collection.

This could be added, but frankly I've stopped enhancing wwSOAP much recently because it's just too much work to keep up with the varying SOAP format issues and ever more complex standards. It gets you 90% of the way there and for the rest of the cases I can use XML parsing in combination with the built in parsing. For example, I can parse an array/collection via DOM, then let wwSOAP handle the individual object parsing...

Another alternative is to use .NET for the Web Service client and then expose that client to COM through VFP. This is ugly and then you need to deal with COM Interop issues, but you at least you'll end up with a reliable Web Service client.


william
October 15, 2005

# re: SOAP Toolkit and Secure Web Service Access

The company i work for actually installs a VB6 COM component that wraps the SOAP toolkit functionality into COM+, creates a local NT user account with the same username/password as required to access the webservice, then sets the COM+ identity to that NT user account.

Creative, isn't it?

The only reason we had to use this stupid soap toolkit was because some smart *architect* at the web service end wanted to return traditional ADODO.Recordset objects, and created a helper class for us to ease the pain. some helper.

Kiwi
January 26, 2006

# re: SOAP Toolkit and Secure Web Service Access

Hello:

Wich is the way to access from VFP to one webService (.net) with this characteristics?

<identity impersonate=true />
<deny users="?" />

I'm trying:
loServicio = loWSHandler.SetupClient("http://username:password@localhost:25002/serviciosIntranet/sweb/servicio1.asmx?wsdl", "Servicio1", "Servicio1Soap")

but always return "loServicio is not an object"

Can you help me?

Thanks and regards




nonubik
May 24, 2006

# re: SOAP Toolkit and Secure Web Service Access

Hi,

I've found this out myself in January 2005, the hard way :( http://www.experts-exchange.com/Programming/Programming_Languages/Dot_Net/Q_21252401.html
But now I have another problem. My wsdl is on https and the trick with the user/pass injection does not work for https. It seems that only adding an extra 's' to the URL (https instead of http) won't do any good :)
Do you have any ideas?

Ron
June 13, 2006

# re: SOAP Toolkit and Secure Web Service Access

nonubik, try using a local copy of the wsdl when you call mssoapinit. Then set your ConnectorProperties and make sure to set the EndPointURL property to point to your https: URL.

Oh and you will have to make direct calls to the SOAP object to do this... something like this:

loservice = CREATEOBJECT('mssoap.soapclient30')
loservice.mssoapinit("yourlocal.wsdl")
loservice.ConnectorProperty("EndPointURL")= "https://www.yoururl.com/Services/UserServices.asmx"
loservice.connectorproperty("UseSSL") = .t.


Taylor Nielsen
August 13, 2006

# re: SOAP Toolkit and Secure Web Service Access


Hi,

We use the SOAP 3.0 toolkit client for intranet apps where we get around the username/password problem for secure webservices by using integrated authentication/delegation. No explicit password is required.

There is a big gotcha, in that the 3.0 toolkit (unlike) the 2.0 toolkit uses the WinHTTP dll and won't support double-hop authentication. (Oops!) The workaround I got from MS was to delete the WHSC30.dll which forces it to use WISC30.dll. Hmmm.

Now the SOAP toolkit EOL, but having an Active-X general-purpose SOAP is so blessedly handy, I wish they would rethink phasing this out. Visual Studio isn't necessily the best web site designer.

Has anyone else tried to use the .NET client with a hand-coded website?

Taylor



Rick Strahl
August 13, 2006

# re: SOAP Toolkit and Secure Web Service Access

I'm pretty sure teh SOAP Toolkit won't be updated any more. Micorosft doesn't have much of a reason to put support into COM client support at this point with all efforts put to .NET.

The stock Web Service client in .NET doesn't support non-WSDL service access. With the WSE extensions you can create manual Soap envelopes and fire them off and I believe WCF lets you do the same.

In most situations where I've needed Web Service support for complex services at this point in COM client application (FoxPro mostly) I tend to use COM Interop to a .NET Web Service client to call the Web Service and pass the data back. The capabiliies of the WS client in .NET goes much beyond what the soap toolkit ever provided so this is usually (but certainly not in all cases) the best choice if the data returned is more complex than simple type values returned.

If you are going to parse the XML manually anyway on the client then bypass a SOAP client altogether and just fire off an HTTP request to the server directly and then parse the XML response manually. for complex responses the SOAP toolkit didn't do much beyond that anyway unless you build those function type definition classes that were more work than parsing the data <s>...


Hiten
June 11, 2007

# re: SOAP Toolkit and Secure Web Service Access

Hi,



I have configured my service to enable security and pass credentials using UserName,Password. I have a custom UserName and Password validator that just authenticates user.



Following is the config file



<configuration>

<system.serviceModel>

<bindings>

<basicHttpBinding>

<binding name="basicBinding">

<security mode="TransportWithMessageCredential">

<transport clientCredentialType="None" />

<message clientCredentialType="UserName"/>

</security>

</binding>

</basicHttpBinding>

</bindings>

<services>

<service behaviorConfiguration="CalculatorServiceBehavior" name="Microsoft.ServiceModel.Samples.CalculatorService">

<endpoint address="wsHttp" binding="wsHttpBinding" contract="Microsoft.ServiceModel.Samples.ICalculator" />

<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />

<endpoint binding="basicHttpBinding" bindingConfiguration="basicBinding"

contract="Microsoft.ServiceModel.Samples.ICalculator" />

<host>

<baseAddresses>

<add baseAddress="https://localhost:4000/ServiceModelSamples/service" />

<add baseAddress="http://localhost/ServiceModelSamples/service" />

</baseAddresses>

</host>

</service>

</services>

<!--For debugging purposes set the includeExceptionDetailInFaults attribute to true-->

<behaviors>

<serviceBehaviors>

<behavior name="UserNamePassword">

<serviceDebug />

<serviceMetadata httpsGetEnabled="true" />

<serviceCredentials>

<userNameAuthentication userNamePasswordValidationMode="Custom"

customUserNamePasswordValidatorType="service.UserNameValidator,service" />

</serviceCredentials>

</behavior>

</serviceBehaviors>

</behaviors>

</system.serviceModel>

</configuration>





As you can see, I want to pass userName and password from client and use it to validate the request. Now question is, when I use my .net client, and call an operation, it does go to the UserNameValidator and I can validate the use, however, I don't know how to pass the credential from SOAP client?



I am using SOAPToolkit 3.0 from client



follwing is the .net client code and it works



CalculatorClient client1 = new CalculatorClient("BasicHttpBinding_ICalculator");

client1.ClientCredentials.UserName.UserName = "asdf";

client1.ClientCredentials.UserName.Password = "asdf";



I tried passing AuthUser, and AuthPassword to ConnectorProperty but it does not work. I get Invalid Verb, Automation Error.



Also I tried providing UserName and password in URL as suggested in some of the posts, but that does not work either...



I am not sure if this feature is supported by SOAPToolkit, If anyone knows how to use this feature from SOAP client, please let me know... It will be a great help to me.



Thanks,

Chum
February 16, 2011

# re: SOAP Toolkit and Secure Web Service Access

Hi, Rick! Your topic was wery usefull for me.

I create web service on Apache Axis2 and use it with MSSoap client

There is BASIC autentication when one connects to service.

Autentication works fine when I conect to servise over http. But what happens when I connect over https? Autentication fails when I use https.

I put my username and password plainly in both cases.

Please tell me how to authorize when I work over https.

Thanks in advance!

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2025