Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Connecting to WS-Security protected Web Service with PHP

I am trying to connect to a Web Service which is password protected and the url is https. I can't figure out how to authenticate before the script makes a request. It seems like it makes a request as soon as I define the service. For instance, if I put in:

$client = new SoapClient("https://example.com/WSDL/nameofservice",        array('trace' => 1,) ); 

and then go to the site on the browser, I get:

Fatal error: Uncaught SoapFault exception:  [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://example.com/WSDL/nameofservice' in /path/to/my/script/myscript.php:2  Stack trace: #0 /path/to/my/script/myscript.php(2):  SoapClient->SoapClient('https://example...', Array) #1 {main} thrown in  /path/to/my/script/myscript.php on line 2 

If I try defining the service as a Soap Server, like:

$server= new SoapServer("https://example.com/WSDL/nameofservice"); 

I get:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <SOAP-ENV:Fault> <faultcode>WSDL</faultcode> <faultstring> SOAP-ERROR: Parsing WSDL:  Couldn't load from 'https://example.com/WSDL/nameofservice' </faultstring> </SOAP-ENV:Fault> </SOAP-ENV:Body> </SOAP-ENV:Envelope> 

I haven't tried sending a raw request envelope yet to see what the server returns, but that may be a workaround. But I was hoping someone could tell me how I can set it up using the php built-in classes. I tried adding "userName" and "password" to the array, but that was no good. The problem is that I can't even tell if I'm reaching the remote site at all, let alone whether it is refusing the request.

like image 571
Anthony Avatar asked Jun 04 '09 23:06

Anthony


1 Answers

Simply extend the SoapHeader to create a Wsse compilant authentication:

class WsseAuthHeader extends SoapHeader {  private $wss_ns = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd';  function __construct($user, $pass, $ns = null) {     if ($ns) {         $this->wss_ns = $ns;     }      $auth = new stdClass();     $auth->Username = new SoapVar($user, XSD_STRING, NULL, $this->wss_ns, NULL, $this->wss_ns);      $auth->Password = new SoapVar($pass, XSD_STRING, NULL, $this->wss_ns, NULL, $this->wss_ns);      $username_token = new stdClass();     $username_token->UsernameToken = new SoapVar($auth, SOAP_ENC_OBJECT, NULL, $this->wss_ns, 'UsernameToken', $this->wss_ns);       $security_sv = new SoapVar(         new SoapVar($username_token, SOAP_ENC_OBJECT, NULL, $this->wss_ns, 'UsernameToken', $this->wss_ns),         SOAP_ENC_OBJECT, NULL, $this->wss_ns, 'Security', $this->wss_ns);     parent::__construct($this->wss_ns, 'Security', $security_sv, true); } }    $wsse_header = new WsseAuthHeader($username, $password); $x = new SoapClient('{...}', array("trace" => 1, "exception" => 0)); $x->__setSoapHeaders(array($wsse_header)); 

If you need to use ws-security with a nonce and a timestamp, Peter has posted an update version on http://php.net/manual/en/soapclient.soapclient.php#114976 of which he wrote that it did work for him:

class WsseAuthHeader extends SoapHeader {     private $wss_ns = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd';     private $wsu_ns = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd';      function __construct($user, $pass)     {         $created    = gmdate('Y-m-d\TH:i:s\Z');         $nonce      = mt_rand();         $passdigest = base64_encode(pack('H*', sha1(pack('H*', $nonce) . pack('a*', $created) . pack('a*', $pass))));          $auth           = new stdClass();         $auth->Username = new SoapVar($user, XSD_STRING, NULL, $this->wss_ns, NULL, $this->wss_ns);         $auth->Password = new SoapVar($pass, XSD_STRING, NULL, $this->wss_ns, NULL, $this->wss_ns);         $auth->Nonce    = new SoapVar($passdigest, XSD_STRING, NULL, $this->wss_ns, NULL, $this->wss_ns);         $auth->Created  = new SoapVar($created, XSD_STRING, NULL, $this->wss_ns, NULL, $this->wsu_ns);          $username_token                = new stdClass();         $username_token->UsernameToken = new SoapVar($auth, SOAP_ENC_OBJECT, NULL, $this->wss_ns, 'UsernameToken', $this->wss_ns);          $security_sv = new SoapVar(             new SoapVar($username_token, SOAP_ENC_OBJECT, NULL, $this->wss_ns, 'UsernameToken', $this->wss_ns),             SOAP_ENC_OBJECT, NULL, $this->wss_ns, 'Security', $this->wss_ns);         parent::__construct($this->wss_ns, 'Security', $security_sv, true);     } } 

compare as well with the details given in answer https://stackoverflow.com/a/18575154/367456

like image 70
Chris Avatar answered Oct 05 '22 23:10

Chris