SOAP Web Service Basic Authentication

Hi All!

I'm developing an integration with a client's system, and to do it I need to call a web service.

Thing is, this web service requires authentication, using the "basic authentication" mode.

Normally this wouldn't be a problem, just add the credentials using the SetWebReferenceCredentials action but it doesn't work.

Upon further analysis, using SoapUI (which I 1000% recommend, by the way), turns out the web service requires what SoapUI calls "pre-emptive authentication":


So, my question is, how can I replicate this behaviour in OutSystems?

Thanks!






Hello Carlos,


Is ardoHTTP an option for you? It supports the Pre-emptive basic authentication.


Thank you,

Armando

Hmm… I'll look into it, the difficulty I need to call a web service, so while that is possible using just HTTP (that, after all, is kinda the whole point of web services), not having all the functionality the platform provides will make it a bit trickier.

But thanks, I hadn't thought of that!

Hi Carlos,

Did you find a solution? I have the same problem, can you please share your solutions?

Best Regards

Hello everyone,

The WS is private, and has authentication through Username and Password.

However I have already solved the issue with SetWebReferenceSoapHeaders, thus adding the necessary credentials in the Header.

Contrary to what I thought, the WS in question does not have Basic authentication, so this solution worked well.

Best Regards

Ivan Barroso wrote:

Hello everyone,

The WS is private, and has authentication through Username and Password.

However I have already solved the issue with SetWebReferenceSoapHeaders, thus adding the necessary credentials in the Header.

Contrary to what I thought, the WS in question does not have Basic authentication, so this solution worked well.

Best Regards

Hi Ivan,

I've got the same issue that needs an authentication before consuming the SOAP WS. U mentioned about SetWebReferenceSoapHeaders. Do u mean to set up this item in Outsystems? If possible, could u pls provide me a small screen capture of where u set this in Outsystems? Pls specify and ur help is mostly appreciated.


Hi Henry,

I am happy to help. 

First off all you need to define the soap header before consuming the WS. For that you must use the SetWebReferenceSoapHeaders like this example:

"<soap:Envelope xmlns:soap='https://www.w3.org/2003/05/soap-envelope' xmlns:acer='https://webservice.pt'>
   <soap:Header>
      <acer:SoapHeaderAuth>
         <!--Optional:-->
         <acer:Username>JohnDoe</acer:Username>
         <!--Optional:-->
         <acer:Password>xptopasswd</acer:Password>
      </acer:SoapHeaderAuth>
   </soap:Header>
</soap:Envelope>"

The you can call the Soap WS.

Best Regards

Hi All,

So, turns out that in my case it was a bit more complicated than I had thought.

Not only did the web service require pre-emptive authentications, that is, the credentials must be sent with the request, it also had issues with the encoding of the response.

In the end I had to create an extension, and using the WCF library I managed to get it working.

Ignoring the problem with the encoding, sending the login information with the request meant adding some extra code:

// create the binding programatically
// this makes this code configuration independent, everything can be passed in as a parameter to this method, instead of being set in a .config file
var bindingElements = new List<BindingElement>();
var httpsBindingElement = new HttpsTransportBindingElement();

bindingElements.Add(httpsBindingElement);
var binding = new CustomBinding(bindingElements);

// create the endpoint address
var endpointAddress = new EndpointAddress(uri);

// now that we have both the binding and the endpoint, use them to create the service client
var client = new [servicereference].[serviceclient](binding, endpointAddress);

// set the *plaintext* credendials
client.ClientCredentials.UserName.UserName = userName;
client.ClientCredentials.UserName.Password = password;

// use Base64 to encode the credentials
// this is required because, when using pre-emptive authorization, the credentials must be Base64 encoded
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(client.ClientCredentials.UserName.UserName + ":" + client.ClientCredentials.UserName.Password);
var base64EncodedCredentials = System.Convert.ToBase64String(plainTextBytes);

// create the authorization header, and add it to the request headers collection
// we'll need this header collection to add it to the request later
var httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] = "Basic " + base64EncodedCredentials;


string response;

// open the channel by creating a context scope for it
using (var scope = new OperationContextScope(client.InnerChannel))
{
// add the headers collection to the request
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;

response = client.doTheThing(...);
}

Hi all,

I've modified to consume the web serv 'getValue' method and it's able to import to Outsystems with a server process created. However, when I run the program, it comes with err: 

The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Basic realm="SOAP Access".


Can anybody give me some hints on this? Thanks.