While following Symfony2 WSSE implementation tutorial, I was annoyed by the suggested WSSE headers interpretation. It only presents HTTP headers, not Soap WSSE headers...
Here is an extract of Symfony2 tutorial, handling HTTP headers :
$wsseRegex = '/UsernameToken Username="([^"]+)", PasswordDigest="([^"]+)", Nonce="([^"]+)", Created="([^"]+)"/';
if (!$request->headers->has('x-wsse') || 1 !== preg_match($wsseRegex, $request->headers->get('x-wsse'), $matches)) {
return;
}
Obviously, it doesn't fit Soap headers that look like that :
2012-10-10T12:00:36.099Z
2012-10-10T12:05:36.099Z
username@email.com
E2wz/+mTabxWO37Hk6UeqSJF8+o=
sAg8czv5GmW7rUKgqhm1Qw==
2012-10-10T12:00:36.099Z
To read these headers, I use SimpleXML after having formatted the raw request content :
<?php
namespace AlterPHP\SoapBundle\Tools;
use Symfony\Component\HttpFoundation\Request;
/**
* Description of WsseHeadersDecoder
*
* @author pece
*/
class WsseHeadersDecoder
{
public function getHeaders(Request $request)
{
//HTTP headers (as described here : http://symfony.com/doc/2.0/cookbook/security/custom_authentication_provider.html#the-listener
if ($request->headers->has('x-wsse'))
{
$wsseRegex = '/UsernameToken Username="([^"]+)", PasswordDigest="([^"]+)", Nonce="([^"]+)", Created="([^"]+)"/';
if (1 !== preg_match($wsseRegex, $request->headers->get('x-wsse'), $matches))
{
return false;
}
else
{
$username = $matches[1];
$passwordDigest = $matches[2];
$nonce = $matches[3];
$created = $matches[4];
}
}
//Classic SOAP headers
else
{
//Clear XML namespace prefixes to handle with SimpleXML
$decodedRequest = preg_replace("/(<\/?)([-\w]+):([^>]*>)/", "$1$3", $request->getContent());
$xmlRequest = simplexml_load_string($decodedRequest);
if (
!isset($xmlRequest->Header->Security->UsernameToken->Username)
|| !isset($xmlRequest->Header->Security->UsernameToken->Password)
|| !isset($xmlRequest->Header->Security->UsernameToken->Nonce)
|| !isset($xmlRequest->Header->Security->UsernameToken->Created)
)
{
return false;
}
else
{
$username = (string) $xmlRequest->Header->Security->UsernameToken->Username;
$passwordDigest = (string) $xmlRequest->Header->Security->UsernameToken->Password;
$nonce = (string) $xmlRequest->Header->Security->UsernameToken->Nonce;
$created = (string) $xmlRequest->Header->Security->UsernameToken->Created;
}
}
return array (
'username' => $username, 'passwordDigest' => $passwordDigest, 'nonce' => $nonce, 'created' => $created
);
}
}