tip

How to authenticate the call to a SOAP web service with PHP 5+

Below is the authenticated request we want to build. It carries a username and password authentication header.

SOAP XML request

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <SOAP-ENV:Header>
    <m:SOAPAuthenticationHeader xmlns:m="http://www.mydomain.com">
      <m:username>myusername</m:username>
      <m:password>mypassword</m:password>
    </m:SOAPAuthenticationHeader>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body>
    <m:WebServiceMethodName xmlns:m="http://www.mydomain.com">
      <m:param1>some value</m:param1>
      <m:param2>some value</m:param2>
      <m:param3>some value</m:param3>
    </m:WebServiceMethodName>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

When we have to use SOAP authentication headers to call a service, we cannot use the intuitive way below, because all of the fields go inside the body part of the envelope (SOAP-ENV Body):

1
2
3
4
5
6
7
8
<?php
$params = new StdClass();
$params->Header->username = "myusername";
$params->Header->password = "mypassword";

$params->Body->param1 = "some value";
$params->Body->param2 = "some value";
$params->Body->param3 = "some value";

The object above is not encoded as a SOAP request with header envelope and body envelope parts - it is simply encoded as body envelope part with child elements header and body. And the request is not properly authenticated.

The solution is to create a separate object to carry the authentication header envelope and a separate object for the body envelope.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
define(WSDL_URL, "http://www.mydomain.com/webservicepath?wsdl");

# create authentication headers (SOAP Header envelope)
$params_header = new stdClass();
$params_header->username = "myusername";
$params_header->password = "mypassword";

# create request parameters (SOAP Body envelope)
$params = new stdClass();
$params->param1 = "some value";
$params->param2 = "some value";
$params->param3 = "some value";

# create soap client object
$soap_client = new SoapClient(WSDL_URL, array("connection_timeout"=>5, 'trace'=>1));

# create soap header object
$soap_header = new SoapHeader("http://www.mydomain.com", "SOAPAuthenticationHeader", $params_header);

# instruct the client to use the SOAP headers we prepared
# when calling the service
$soap_client->__setSoapHeaders(array($soap_header));

try
{
  # call the method of the service
  $result = $soap_client->WebServiceMethodName(params);
}
catch(SoapFault $exception)
{
  echo $exception;
}