0

I am trying to use Delphi and Indy's TIdHTTP to access a site using the security usernametoken aspect.

The SOAP request has headers for password type=urladdressforoasis password

The server's classnameproxy.config file from the vendor has this:

<basicHttpBinding>
    <binding name="BasicHttpBinding_ZZ_myInt">
        <security mode="TransportWithMessageCredential" />
    </binding>
</basicHttpBinding>

So I am trying to add custom headers to TIdHTTP using the following code:

idHTTP.Request.CustomHeaders.AddValue('Authorization', 'Basic ' + TIdEncoderMIME.EncodeString(string(aUserID) + ':' + string(aPWD), IndyTextEncoding_ASCII()));

Obviously this is incorrect for some reason. I have looked around for TIdHTTP and oasis and usernametoken but found nothing. Maybe I am looking for the wrong keywords?

Is it possible to use TIdHTTP to access web services using a security usernametoken?

function Post_XML(aURL, aUserID, aPWD, aInputFile, aOutputFile, aContentType, aCharset, aShow: pAnsiChar):integer; stdcall;
var
  sRequest,
  sResponse : TFileStream;
  idHTTP  : TidHTTP;
  SSLHandler : TidSSLIOHandlerSocketOpenSSL;
  EnvVar  : string;
begin
  Result := 0;
  begin
    try
    begin
      sRequest := TFileStream.Create(string(aInputFile), fmOpenRead or fmShareDenyWrite);
      sResponse := TFileStream.Create(string(aOutputFile), fmCreate or fmShareDenyRead or fmOpenWrite);
    end;
    except on E: Exception do
    begin
      Result := 99;
    end;
    end;
    try
    begin
      EnvVar := '';
      EnvVar := System.SysUtils.GetEnvironmentVariable('use_a_proxy');
      SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create;
      SSLHandler.SSLOptions.SSLVersions := [sslvSSLv23, sslvSSLv3, sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
      SSLHandler.SSLOptions.Mode := sslmUnassigned;
      idHTTP := TidHTTP.Create;
      idHTTP.ConnectTimeout := 60000;
      idHTTP.ReadTimeout := 60000;
      idHTTP.HandleRedirects := True;
      idHTTP.IOHandler := SSLHandler;
      if UpperCase(EnvVar) = 'ON' then
      begin
        idHTTP.ProxyParams.ProxyServer := '127.0.0.1';
        idHTTP.ProxyParams.ProxyPort := 8888;
      end;
      idHTTP.Request.ContentType := string(aContentType);
      idHTTP.Request.CharSet := string(aCharSet);
      idhttp.Request.CustomHeaders.AddValue('SOAPAction', 'http://bustax.tntax.tn.gov/BusTaxRequest');
      if aUserid <> '' then
      begin
        idHTTP.Request.BasicAuthentication := True;
        idhttp.Request.Username := aUserid;
        idHTTP.Request.Password := aPwd;
      end;
      idHTTP.Post(trim(string(aURL)), sRequest, sResponse);
      FreeAndNil(SSLHandler);
      FreeAndNil(idHTTP);
    end;
    except
      on E: EIdHTTPProtocolException do
      begin
        ShowMessage(AnsiString('Protocol Error: ' + E.Message));
        Result := E.ErrorCode;
       end;
      on E: EIdSocketError  do
      begin
        ShowMessage(AnsiString('Socket Error: ' + E.Message));
        Result := E.LastError;
      end;
      on E: EIdException  do
      begin
        ShowMessage(AnsiString('HTTP Error: ' + E.Message));
        Result := HTTPMain.ResponseCode;
      end;
      on E: Exception  do
      begin
        ShowMessage(AnsiString('Error: ' + E.Message));
        Result := HTTPMain.ResponseCode;
      end;
    end;
    FreeAndNil(sRequest);
    FreeAndNil(sResponse);
    end;
end;
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:oas="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:bus="http://bustax.tntax.tn.gov">
<soapenv:Header>
<oas:Security>
<oas:UsernameToken>
<oas:Username>myUsername</oas:Username>
<oas:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">myPassword</oas:Password>
</oas:UsernameToken>
</oas:Security>
</soapenv:Header>
<soapenv:Body>
<bus:BusTaxRequest>
<bus:JurisdictionSITUS>1900</bus:JurisdictionSITUS>
<bus:TransactionId>123456</bus:TransactionId>
</bus:BusTaxRequest>
</soapenv:Body>
</soapenv:Envelope>
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
RDT
  • 1
  • 7
  • here is sample xml they said to use in Soap UI and it seems to work. – RDT Apr 27 '18 at 16:00
  • myUserId myPassword 1900 123456 – RDT Apr 27 '18 at 16:01
  • `TIdHTTP` has built-in support for HTTP's `Basic` authentication. Assign `TIdHTTP`'s `Request.UserName` and `Request.Password` properties as needed, and set its `Request.BasicAuthentication` property to true. Do not use the `Request.CustomHeaders` property for `Basic` authentication. – Remy Lebeau Apr 27 '18 at 16:20
  • That being said, OASIS does not use HTTP authentication, login credentials are transmitted in XML elements within the SOAP messages instead. See [Web Services Security: UsernameToken Profile 1.0](http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf) and [Web Services Security: UsernameToken Profile 1.1](https://www.oasis-open.org/committees/download.php/16782/wss-v1.1-spec-os-UsernameTokenProfile.pdf) for details (other OASIS specs are available at https://www.oasis-open.org). – Remy Lebeau Apr 27 '18 at 16:22
  • Thank you for the links and i learned a little but not enough. When i use a saved xml in SOAPUI and paste it in there it works. but when i use idhttp to send it i get a 500 internal error. – RDT Apr 29 '18 at 04:54
  • Please edit your question to add details instead of posting them in comments. And please show the actual code you are using to prepare `TIdHTTP` and send the XML. – Remy Lebeau Apr 29 '18 at 05:04
  • FYI: Userid and pwd are empty, so no authentication is set that way. the proxy settings are not being used, no environment variable is set. – RDT Apr 30 '18 at 13:23
  • OK in my testing i found that by adding the customheaders for the soapaction it works – RDT Apr 30 '18 at 15:57
  • What's with all the `AnsiString` type-casts? You don't need those at all. Also, you are leaking the `TIdHTTP` and `TIdSSLIOHandlerSocketOpenSSL` objects. – Remy Lebeau Apr 30 '18 at 17:10
  • Sorry the code does have the Free commands, its just way down after a bunch of other code unrelated to the idhttp.post. as for the ansistring sorry that was just pure laziness on my part since originally it was System.AnsiStrings.strlcopy(aError, PAnsiChar(AnsiString('Socket Error: ' + E.Message)), Length('Socket Error: ' + E.Message)); and i changed the dll to just display the message on its own since multiple coders were not displaying the error message when they got it back. – RDT Apr 30 '18 at 18:46
  • since we already use the Post_It function in multiple programs on other development platform (COBOL, 100+ programs) i will just be creating a new exported function that allows headers to be passed in. – RDT Apr 30 '18 at 18:49

0 Answers0