1

I need to consume a SOAP 1.2 web service which uses WS-Security. The platforms I use at work are Delphi 10.2 Tokyo and .Net Core. Neither of these seem to work.

  • Am I doing something wrong when consuming the web services?
  • If not, what are my other alternatives for platforms? I'm open to any suggestions. With as much built-in support for the below WSDL as possible. The app I'm building needs to be a Windows app.

When trying with Delphi 10.2 Tokyo's built in WSDL importer (using SOAP 1.2 with Indy), my requests are sent without any SOAP header information. This invalid request throws the error Connection reset by peer.

When trying with .Net Core (using WCF Web Service Reference Provider) I get the error: System.PlatformNotSupportedException: 'TransportSecurityBindingElement.BuildChannelFactoryCore is not supported.'

Presumably due to the required feature not being supported by .Net Core yet: https://github.com/dotnet/wcf/blob/master/release-notes/SupportedFeatures-v2.0.0.md (Security.Message isn't supported)

Below is the WSDL. I have trimmed unnecessary XML from this file, and replaced the actual company name with Example. Hopefully this will give enough of an idea of what the WSDL policies/requirements are.

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:i0="http://tempuri.org/"
    xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:tns="www.example.com/ExampleService"
    xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
    xmlns:wsa10="http://www.w3.org/2005/08/addressing"
    xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
    xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy"
    xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    name="ExampleService"
    targetNamespace="www.example.com/ExampleService">
    <wsp:Policy wsu:Id="ExampleAPI_policy">
        <wsp:ExactlyOne>
            <wsp:All>
                <sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
                    <wsp:Policy>
                        <sp:TransportToken>
                            <wsp:Policy>
                                <sp:HttpsToken RequireClientCertificate="false" />
                            </wsp:Policy>
                        </sp:TransportToken>
                        <sp:AlgorithmSuite>
                            <wsp:Policy>
                                <sp:Basic256 />
                            </wsp:Policy>
                        </sp:AlgorithmSuite>
                        <sp:Layout>
                            <wsp:Policy>
                                <sp:Strict />
                            </wsp:Policy>
                        </sp:Layout>
                        <sp:IncludeTimestamp />
                    </wsp:Policy>
                </sp:TransportBinding>
                <sp:EndorsingSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
                    <wsp:Policy>
                        <sp:SecureConversationToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
                            <wsp:Policy>
                                <sp:BootstrapPolicy>
                                    <wsp:Policy>
                                        <sp:SignedParts>
                                            <sp:Body />
                                            <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
                                            <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />
                                            <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" />
                                            <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" />
                                            <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />
                                            <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />
                                            <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />
                                        </sp:SignedParts>
                                        <sp:EncryptedParts>
                                            <sp:Body />
                                        </sp:EncryptedParts>
                                        <sp:TransportBinding>
                                            <wsp:Policy>
                                                <sp:TransportToken>
                                                    <wsp:Policy>
                                                        <sp:HttpsToken RequireClientCertificate="false" />
                                                    </wsp:Policy>
                                                </sp:TransportToken>
                                                <sp:AlgorithmSuite>
                                                    <wsp:Policy>
                                                        <sp:Basic256 />
                                                    </wsp:Policy>
                                                </sp:AlgorithmSuite>
                                                <sp:Layout>
                                                    <wsp:Policy>
                                                        <sp:Strict />
                                                    </wsp:Policy>
                                                </sp:Layout>
                                                <sp:IncludeTimestamp />
                                            </wsp:Policy>
                                        </sp:TransportBinding>
                                        <sp:SignedSupportingTokens>
                                            <wsp:Policy>
                                                <sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
                                                    <wsp:Policy>
                                                        <sp:WssUsernameToken10 />
                                                    </wsp:Policy>
                                                </sp:UsernameToken>
                                            </wsp:Policy>
                                        </sp:SignedSupportingTokens>
                                        <sp:Wss11>
                                            <wsp:Policy />
                                        </sp:Wss11>
                                        <sp:Trust10>
                                            <wsp:Policy>
                                                <sp:MustSupportIssuedTokens />
                                                <sp:RequireClientEntropy />
                                                <sp:RequireServerEntropy />
                                            </wsp:Policy>
                                        </sp:Trust10>
                                    </wsp:Policy>
                                </sp:BootstrapPolicy>
                            </wsp:Policy>
                        </sp:SecureConversationToken>
                    </wsp:Policy>
                </sp:EndorsingSupportingTokens>
                <sp:Wss11 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
                    <wsp:Policy />
                </sp:Wss11>
                <sp:Trust10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
                    <wsp:Policy>
                        <sp:MustSupportIssuedTokens />
                        <sp:RequireClientEntropy />
                        <sp:RequireServerEntropy />
                    </wsp:Policy>
                </sp:Trust10>
                <wsaw:UsingAddressing />
            </wsp:All>
        </wsp:ExactlyOne>
    </wsp:Policy>
    <wsp:Policy wsu:Id="ExampleAPI2_policy">
        <wsp:ExactlyOne>
            <wsp:All>
                <sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
                    <wsp:Policy>
                        <sp:TransportToken>
                            <wsp:Policy>
                                <sp:HttpsToken RequireClientCertificate="false" />
                            </wsp:Policy>
                        </sp:TransportToken>
                        <sp:AlgorithmSuite>
                            <wsp:Policy>
                                <sp:Basic256 />
                            </wsp:Policy>
                        </sp:AlgorithmSuite>
                        <sp:Layout>
                            <wsp:Policy>
                                <sp:Lax />
                            </wsp:Policy>
                        </sp:Layout>
                        <sp:IncludeTimestamp />
                    </wsp:Policy>
                </sp:TransportBinding>
                <sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
                    <wsp:Policy>
                        <sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
                            <wsp:Policy>
                                <sp:WssUsernameToken10 />
                            </wsp:Policy>
                        </sp:UsernameToken>
                    </wsp:Policy>
                </sp:SignedSupportingTokens>
                <sp:Wss10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
                    <wsp:Policy />
                </sp:Wss10>
            </wsp:All>
        </wsp:ExactlyOne>
    </wsp:Policy>
    <wsdl:types>

        <!-- trimmed away types -->

    </wsdl:types>

    <!-- trimmed away messages -->

    <wsdl:portType name="IAPIService">

        <!-- trimmed away operations -->

    </wsdl:portType>
    <wsdl:binding name="ExampleAPI" type="tns:IAPIService">
        <wsp:PolicyReference URI="#ExampleAPI_policy" />
        <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />

        <!-- trimmed away operations -->

    </wsdl:binding>
    <wsdl:binding name="ExampleAPI2" type="tns:IAPIService">
        <wsp:PolicyReference URI="#ExampleAPI2_policy" />
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />

        <!-- trimmed away operations -->

    </wsdl:binding>
    <wsdl:service name="ExampleService">
        <wsdl:port name="ExampleAPI" binding="tns:ExampleAPI">
            <soap12:address location="https://example.com/apps/api/APIService.svc" />
            <wsa10:EndpointReference>
                <wsa10:Address>https://example.com/apps/api/APIService.svc</wsa10:Address>
            </wsa10:EndpointReference>
        </wsdl:port>
        <wsdl:port name="ExampleAPI2" binding="tns:ExampleAPI2">
            <soap:address location="https://example.com/apps/api/APIService.svc/endpoint2" />
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

2 Answers2

3

There's no specific 'best' platform to consume a webservice. However, some platforms support the automatic generation of proxy classes better than others.

When trying with Delphi 10.2 Tokyo's built in WSDL importer (using SOAP 1.2 with Indy), my requests are sent without any SOAP header information.

I don't have experience with .NET Core, but when using Delphi 10.2 you need to manually add (Send) the SOAP header before you send your request.

This can be done by casting the webservice instance to ISOAPHeaders

Example:

procedure TestSendHeader;
var
  MyService: IMySoapWebservice;
  header : TMySoapHeader;
begin
  MyService := GetMySoapService();
  (MyService as ISOAPHeaders).OwnsSentHeaders := True;

  // Create header object
  header := TMySoapHeader.Create;
  // Fill header data
  // header.xyz := ;
  // 'Send' header with the request
  (MyService as ISOAPHeaders).Send(header);

  MyResponse := MyService.DoMyRequest();
end;

Setting OwnsSentHeaders to true wil free up the created header object, after the request has been sent.

NOTE: you have to 'Send' the header each time you make a request:

  // 'Send' header with the request 1
  (MyService as ISOAPHeaders).Send(header);    
  MyResponse := MyService.DoMyRequest1();

  // 'Send' header with the request 2
  (MyService as ISOAPHeaders).Send(header);    
  MyResponse := MyService.DoMyRequest2();

In this case, don’t set OwnsSentHeaders to true and free the header object after you’re done, sending requests.

R. Hoek
  • 916
  • 8
  • 27
  • Does this mean that I would have to implement the WS-Security and WS-Addressing features myself? Seems like a huge task to take on, as it involves encryption, signing the data, etc. Maybe someone has already done the heavy lifting and put it on GitHub? Haven't found anything though... – P. Bergström May 30 '19 at 15:28
  • 2
    I have some code regarding then basic structure of WS-security (xml-object) which I will look up tomorrow. But the data encrypting (base64 encoding) is not part of that, so you have to do that yourself. – R. Hoek May 30 '19 at 20:33
  • 1
    I posted the Delphi code regarding the WS-Security header. Note there are two versions (at least that I know of) - 2003.06 and 2004.01. Both are added in the gist: https://gist.github.com/ronaldhoek/ff7611a0b4bd03c01f72c3dd5a4f0a5c – R. Hoek May 31 '19 at 11:02
  • Also regarding encoding, Delphi has a unit called 'System.NetEncoding' (start Delphi 10 or so) which will help in encoding/decoding data. – R. Hoek May 31 '19 at 11:03
  • Thank you very much. I'll take a look at WS-security in Delphi when I've some free time. Looks promising. In the mean time I've decided to go with developing a .NET Framework DLL that Delphi can use. – P. Bergström Jun 02 '19 at 15:16
0

.NET Framework has full support for the SOAP service. I've developed a .NET Framework app in C#, and built a DLL which can be used by Delphi, .NET Core, etc. It's a bit of a roundabout solution, yet the easiest one I could find.

Accessing services in C#: https://learn.microsoft.com/en-us/dotnet/framework/wcf/accessing-services-using-a-wcf-client

Export DLL functions: Is is possible to export functions from a C# DLL like in VS C++?