I am writing a PHP script which needs to get an Assertion token as part of a process to log into SharePoint online. I am able to get an envelope response which includes the token I need.
How would I parse out the saml:Assertion portion of this response?
<s:Envelope xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue</a:Action>
<o:Security xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" s:mustUnderstand="1">
<u:Timestamp u:Id="_0">
<u:Created>2014-07-01T13:50:22.480Z</u:Created>
<u:Expires>2014-07-01T13:55:22.480Z</u:Expires>
</u:Timestamp>
</o:Security>
</s:Header>
<s:Body>
<t:RequestSecurityTokenResponse xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<t:Lifetime>
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2014-07-01T13:50:22.476Z</wsu:Created>
<wsu:Expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2014-07-01T14:50:22.476Z</wsu:Expires>
</t:Lifetime>
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Address>urn:federation:MicrosoftOnline</wsa:Address>
</wsa:EndpointReference>
</wsp:AppliesTo>
<t:RequestedSecurityToken>
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" MajorVersion="1" MinorVersion="1" AssertionID="_56f0eee3-ca21-4885-a40d-4ae543e9bfc8" Issuer="http://paychex.com/adfs/services/trust/" IssueInstant="2014-07-01T13:50:22.480Z">
<saml:Conditions NotBefore="2014-07-01T13:50:22.476Z" NotOnOrAfter="2014-07-01T14:50:22.476Z">
<saml:AudienceRestrictionCondition>
<saml:Audience>urn:federation:MicrosoftOnline</saml:Audience>
</saml:AudienceRestrictionCondition>
</saml:Conditions>
<saml:AttributeStatement>
<saml:Subject>
<saml:NameIdentifier Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">qo3X1/EAe0Ci5pXaS+p8JA==</saml:NameIdentifier>
<saml:SubjectConfirmation>
<saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Attribute AttributeName="UPN" AttributeNamespace="http://schemas.xmlsoap.org/claims">
<saml:AttributeValue>email#email.com</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute AttributeName="ImmutableID" AttributeNamespace="http://schemas.microsoft.com/LiveID/Federation/2008/05">
<saml:AttributeValue>qo3X1/p8JA==</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
<saml:AuthenticationStatement AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:password" AuthenticationInstant="2014-07-01T13:50:22.473Z">
<saml:Subject>
<saml:NameIdentifier Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">qo3X1/EAe0p8JA==</saml:NameIdentifier>
<saml:SubjectConfirmation>
<saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod>
</saml:SubjectConfirmation>
</saml:Subject>
</saml:AuthenticationStatement>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#_56f0eee3-ca21-4885-a40d-4ae543e9bfc8">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>ZzoryFYQWfks=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>UnHrvM3vUE6l4HlpsuBX7E79750MNWASBuVNIVJ01QJSID8w3IHkjfMWCjidty7F96obL5Ah6o/UY55dMjbiyWt9gyToQPrGBPjG+VX3pEz8XpXV4jrYYXJ/YMpHxdzD/OBzR/bpA+lzebkuP19woqV49ScmJ5TN4b26LEW/ynogYnNl7EEBAJR0wL9CjY6uQCNaERY0X29nyNusQyNTNW4jGeMyBu9KnfVRpVyROd4QxfwV/F8OwGlePRGPypN/VYnLRjfizS674XJ31VmLERwxgn5Xx/0bKDsNw7c5G2qFZmSi7YUxccwMxU6Ypih7D5i73uPrk7oMnRbMHsyxCQ==</ds:SignatureValue>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Data>
<X509Certificate>MIIC3DCCAcSgAwIBAgIQXIfoKmHCypFBv4Ze44WbzzANBgkqhkiG9w0BAQsFADAqMSgwJgYDVQQDEx9BREZTIFNpZ25pbmcgLSBhZGZzLnBheWNoZXguY29tMB4XDTE0MDQyNDAyMDY1NloXDTE5MDQyMzAyMDY1NlowKjEoMCYGA1UEAxMfQURkhc6NJSB8fJK+Uf/ldkC8VISTp7CW9S3TwXHKn4plqMLSY7NRYII4OPDkLXA9dGx3FQGNQoTe/uH1JGaNZlAGJp4W2Sz9r1i9Ry4lu+L0G3Q==</X509Certificate>
</X509Data>
</KeyInfo>
</ds:Signature>
</saml:Assertion>
</t:RequestedSecurityToken>
<t:RequestedAttachedReference>
<o:SecurityTokenReference xmlns:k="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" k:TokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">
<o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID">_56f0eee3-ca21-4885-a40d-4ae543e9bfc8</o:KeyIdentifier>
</o:SecurityTokenReference>
</t:RequestedAttachedReference>
<t:RequestedUnattachedReference>
<o:SecurityTokenReference xmlns:k="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" k:TokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">
<o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID">_56f0eee3-ca21-4885-a40d-4ae543e9bfc8</o:KeyIdentifier>
</o:SecurityTokenReference>
</t:RequestedUnattachedReference>
<t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
<t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>
</t:RequestSecurityTokenResponse>
</s:Body>
</s:Envelope>
My PHP code snippet to parse this response is:
// Parse security token from response
$xml = new DOMDocument();
$xml->loadXML($result);
$xpath = new DOMXPath($xml);
$nodelist = $xpath->query("/*[local-name()='name']:Body/*[local-name()='name']:RequestSecurityTokenResponse/*[local-name()='name']:RequestedSecurityToken/*[local-name()='name']:Assertion");
foreach ($nodelist as $n){
return $n->nodeValue;
break;
}
Thanks for all your help,
Tim
I tried using //saml:Assertion but it did not work
You need to register the namespace prefix first - XPath expressions do not care what prefixes were used in the original document, you need to bind prefixes to namespaces yourself.
$xpath->registerNamespace("s", "urn:oasis:names:tc:SAML:1.0:assertion");
$nodelist = $xpath->query("//s:Assertion");
But this will probably still give you null because the "node value" of an element node in the DOM is defined in the spec to always be null. If you want the text inside an element node then you need to use textContent instead of nodeValue, but in this case you'll probably have to dig deeper into the tree to find the bit you actually want.
To simply extract the value, in XPath 1.0 you can use the following expression, which ignores namespaces:
/*[local-name()='Envelope']
/*[local-name()='Body']
/*[local-name()='RequestSecurityTokenResponse']
/*[local-name()='RequestedSecurityToken']
/*[local-name()='Assertion']
or using the descendant axis:
//*[local-name()='Assertion']
Ignoring namespaces should be a second option. If you can register them as suggested by #IanRoberts in the other answer it is better.
Any of these expressions will return a node-set containing all the Assertion elements found (the whole tree). The node value or text content of these nodes may not be what you want to select. For example, if you want to get the X509Certificate you should use a contextual XPath expression to that element and extract its text(). Same strategy should be used if you want an attribute of a child element.
Update The PHP code you added uses a for loop just to extract the first node. You could use item(0) for that. Assuming there is only one assertion, key, certificate, etc, in each document, you can use XPath expressions to extract exactly what you want. For example, to get the X509Certificate text (ignoring namespaces and intermediate location steps) you could use:
$key_cert = $xpath->query("//*[local-name()='X509Certificate']")->item(0)->textContent
Related
I've got XML containing XAdES-BES digita signature:
<?xml version="1.0" encoding="UTF-8"?>
<Signatures Id="ID-222cf3cf-0f0b-49d2-b7cb-4cf47bb373cb">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="ID-9a61610b-c8e3-4201-bf41-a174cbc21634">
<ds:SignedInfo Id="ID-8ebe3e85-1413-4fec-a14c-7264546ab770">
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<ds:Reference Id="ID-e751928b-6823-47ad-a5ae-b7ccdf301751" URI="#ID-e37958b8-134c-4f51-9b25-8274fd1edce7">
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>Z7q3zqS5FTNPP/mj0rDmUV5PdZQ=</ds:DigestValue>
</ds:Reference>
<ds:Reference Id="ID-396858b0-7e4b-42e1-ba5f-18368f90f0df" URI="#ID-90b9721b-1d1c-4104-ae2c-ebb6b251cf2b" Type="http://uri.etsi.org/01903#SignedProperties">
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>H7EeV4pPoJ6WhWFnVSo3WNu3Yj8=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue Id="ID-949000f9-85bc-435e-b387-8f7aa5551d75">a0cc/hQYjmwQC8ssBzolLyArUqOVi+s6cP+lbxku69qGleBUroQlvD6o+GpIxSJB6wlWwic3YjuxDxn9
mfW2jCLYEEM1RB277ChnHASakC+vbBP03LWC+GxsOe0seKMVsCc0EPwS5kk5RfvrUN6sTxWSW/2MOIXG
4fW1cAtjh1SjDN9Ij38SIuWpW8guJ9EGEVyTUuTiZ5dbpHfxftgKfHmr16aMpXk0ta46X2UuGTQRB+E/
0W+RpLqdmTP5VG0CxT8Z2H4n6puGL0yC20SsZZDethL/Vnr67EXTPmHFUwoZOGNu+0IFdBJW4HvLA5rF
czL82MOsCoFXqzMVxGxiqw==</ds:SignatureValue>
<ds:KeyInfo>
<ds:KeyValue>
<ds:RSAKeyValue>
<ds:Modulus>AL4k+zz02RytjonBY0af0dfuuDJhNg0dypClqzkLyyLjkTa9QUbtdtA20lRuogjFqb6CVpqQ/PEdXDK5
bN6qGBQGsmdqkgru6A8aAc57QawEcbEL+rDue1L+mqM/JVnr+DAWOehITd8HzS0JQTQcxF1Lv0L1GNbJ
P8/bo8Coj2EVtKZ9tBI9+AZUdZ11uKBYj9uvKy0VGufjoljIIrQASIft4nw8a/WF+beEYOrl3PqnBcAo
Lc/CJiNsnsASws0a/EKuaP3vQbIo36s7FVH7U4x/8ypcAPsmtgi9LbH+v9Ugc2CiCj7krJIT3X9EwkjC
FUq+MykmVvfW0D0bOTP2X5k=</ds:Modulus>
<ds:Exponent>AQAB</ds:Exponent>
</ds:RSAKeyValue>
</ds:KeyValue>
<ds:X509Data>
<ds:X509Certificate>MIIGETCCBPmgAwIBAgIUaQ+g3SS0YfvHQus43mbJ+4FSYegwDQYJKoZIhvcNAQEFBQAwczELMAkGA1UE
BhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xJDAiBgNVBAMMG0NP
UEUgU1pBRklSIC0gS3dhbGlmaWtvd2FueTEUMBIGA1UEBRMLTnIgd3Bpc3U6IDYwHhcNMTUxMDA4MTIw
MDAwWhcNMTYxMDA4MTIwMDAwWjB2MQswCQYDVQQGEwJQTDEbMBkGA1UEBRMSUEVTRUw6IDg2MDYxMzE0
Mzk3MR8wHQYDVQQDDBZLYW1pbCBTZWJhc3RpYW4gTWlqYWN6MRgwFgYDVQQqDA9LYW1pbCBTZWJhc3Rp
YW4xDzANBgNVBAQMBk1pamFjejCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL4k+zz02Ryt
jonBY0af0dfuuDJhNg0dypClqzkLyyLjkTa9QUbtdtA20lRuogjFqb6CVpqQ/PEdXDK5bN6qGBQGsmdq
kgru6A8aAc57QawEcbEL+rDue1L+mqM/JVnr+DAWOehITd8HzS0JQTQcxF1Lv0L1GNbJP8/bo8Coj2EV
tKZ9tBI9+AZUdZ11uKBYj9uvKy0VGufjoljIIrQASIft4nw8a/WF+beEYOrl3PqnBcAoLc/CJiNsnsAS
ws0a/EKuaP3vQbIo36s7FVH7U4x/8ypcAPsmtgi9LbH+v9Ugc2CiCj7krJIT3X9EwkjCFUq+MykmVvfW
0D0bOTP2X5kCAwEAAaOCApgwggKUMAwGA1UdEwEB/wQCMAAwggFPBgNVHSABAf8EggFDMIIBPzCCATsG
CSqEaAGG9yMBATCCASwwgd0GCCsGAQUFBwICMIHQDIHNRGVrbGFyYWNqYSB0YSBqZXN0IG/Fm3dpYWRj
emVuaWVtIHd5ZGF3Y3ksIMW8ZSB0ZW4gY2VydHlmaWthdCB6b3N0YcWCIHd5ZGFueSBqYWtvIGNlcnR5
ZmlrYXQga3dhbGlmaWtvd2FueSB6Z29kbmllIHogd3ltYWdhbmlhbWkgdXN0YXd5IG8gcG9kcGlzaWUg
ZWxla3Ryb25pY3pueW0gb3JheiB0b3dhcnp5c3rEhWN5bWkgamVqIHJvenBvcnrEhWR6ZW5pYW1pLjBK
BggrBgEFBQcCARY+aHR0cDovL3d3dy5lbGVrdHJvbmljem55cG9kcGlzLnBsL2luZm9ybWFjamUvZG9r
dW1lbnR5LWktdW1vd3kwCQYDVR0JBAIwADAhBgNVHREEGjAYgRZrYW1pbC5taWphY3pAZ21haWwuY29t
MA4GA1UdDwEB/wQEAwIGQDCBsAYDVR0jBIGoMIGlgBTMQSp2mC5KehnakTbf2H85P9TCrqF3pHUwczEL
MAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xJDAiBgNV
BAMMG0NPUEUgU1pBRklSIC0gS3dhbGlmaWtvd2FueTEUMBIGA1UEBRMLTnIgd3Bpc3U6IDaCFH18c1x7
vNOu01acH+WfGYiAcun0MEAGA1UdHwQ5MDcwNaAzoDGGL2h0dHA6Ly9lbGVrdHJvbmljem55cG9kcGlz
LnBsL2NybC9jcmxfb3prNTIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQAP0zddWprl5hpXiIiMGcC5D7ob
/nj3wvfOUm0QCf7+ZEorfr6EC96B6F/cNtZ1wXtAQXkf5Zm3gPhbKXY6XWM2NDWadZrDV9zV75Ab06dQ
5qmDfuMGTfPUdH3+QBmW7YnniWPCGuMzGNlP9DpZ45YrgRnwlsZSHMhX0HiEeDfYKAkGhIaJ7lcPlZrj
zWBdhUOgYm06pYf8NEKVWzu808iIHIvCBot0ADcZ8ypxDyQsco/RSRGY0EO8FATCH3j2Oe/+7FGRjRQK
XczBsKu6G8GQ6b/eGuWD7NNAuBX4UJu9jXRo9mzo7zKj01/SPfE4kHTHfHr9yi9BBkzAmaAxQpT5</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
<ds:Object>
<xades:QualifyingProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" Id="ID-04b0ddeb-914c-419f-acb2-780dae2ee890" Target="#ID-9a61610b-c8e3-4201-bf41-a174cbc21634">
<xades:SignedProperties Id="ID-90b9721b-1d1c-4104-ae2c-ebb6b251cf2b">
<xades:SignedSignatureProperties>
<xades:SigningTime>2015-12-08T13:37:16Z</xades:SigningTime>
<xades:SigningCertificate>
<xades:Cert>
<xades:CertDigest>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>+6UE5SSks6Cn6++o8CAkSO/NMWk=</ds:DigestValue>
</xades:CertDigest>
<xades:IssuerSerial>
<ds:X509IssuerName>serialNumber=Nr wpisu: 6,CN=COPE SZAFIR - Kwalifikowany,O=Krajowa Izba Rozliczeniowa S.A.,C=PL</ds:X509IssuerName>
<ds:X509SerialNumber>599792555331422089182929030726347827824527827432</ds:X509SerialNumber>
</xades:IssuerSerial>
</xades:Cert>
</xades:SigningCertificate>
</xades:SignedSignatureProperties>
<xades:SignedDataObjectProperties>
<xades:DataObjectFormat ObjectReference="#ID-e751928b-6823-47ad-a5ae-b7ccdf301751">
<xades:Description>Dokument w formacie xml [XML]</xades:Description>
<xades:MimeType>text/plain</xades:MimeType>
<xades:Encoding>http://www.w3.org/2000/09/xmldsig#base64</xades:Encoding>
</xades:DataObjectFormat>
</xades:SignedDataObjectProperties>
</xades:SignedProperties>
</xades:QualifyingProperties>
</ds:Object>
<ds:Object Encoding="http://www.w3.org/2000/09/xmldsig#base64" Id="ID-e37958b8-134c-4f51-9b25-8274fd1edce7" MimeType="text/plain">PFRyZXNjUGlzbWE+DQogIDxTeWduYXR1cmFBa3Q+QUJDWFlaMTIzPC9TeWduYXR1cmFBa3Q+DQogIDxQ
b2RtaW90eT4NCiAgICA8UG9kbWlvdD4NCiAgICAgIDxPc29iYUZpenljem5hPg0KICAgICAgICA8SW1p
ZT5KYW51c3o8L0ltaWU+DQogICAgICAgIDxOYXp3aXNrbz5Ob3dhazwvTmF6d2lza28+DQogICAgICAg
IDxPem5hY3plbmllPg0KICAgICAgICAgIDxQZXNlbD44OTEwMDEwMDYxNjwvUGVzZWw+DQogICAgICAg
IDwvT3puYWN6ZW5pZT4NCiAgICAgIDwvT3NvYmFGaXp5Y3puYT4NCiAgICA8L1BvZG1pb3Q+DQogIDwv
UG9kbWlvdHk+DQogIDxQb2RzdGF3YVByYXduYT4NCiAgICA8UG9kc3Rhd2E+UFBfMDA0PC9Qb2RzdGF3
YT4NCiAgPC9Qb2RzdGF3YVByYXduYT4NCjwvVHJlc2NQaXNtYT4=</ds:Object>
</ds:Signature>
</Signatures>
When I load it with simplexml_load_string, var_dump shows:
object(SimpleXMLElement)#212 (1) {
["#attributes"] => array(1) {
["Id"] => string(39) "ID-222cf3cf-0f0b-49d2-b7cb-4cf47bb373cb"
}
}
There's no nested nodes of "Signatures" data.
However, when I remove "ds" namespaces from tags, it works great.
How can I get them without changing document?
Thanks to the michi's comment, I found a solution. Namespaced nodes should be accessed differently than nodes without namespace.
So, basing on the example above, when I want to use Signature node, I can do it like this:
$xml = simplexml_load_string($content);
$signatureNode = $xml->children('ds', true)->Signature;
sorry of my English :) .
I neeed to write signing block in XML like it:
ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gost34310-gost34311"/>
<ds:Reference>
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gost34311"/>
<ds:DigestValue>drvEZVSz3nSXHVI6+iRSDXZDGud9Ay56LLfMkpQkRp4=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>/4ASSFXCsdsdMuwM9kw0riDbhhtLR/+UKZKNO51HbACu5DM
SLmmAmp5FwFHdsGtBQ==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
I find this in GIT : https://github.com/Maks3w/xmldsig
my code is:
$data = new DOMDocument();
$data->load(__DIR__ . '/newdata.xml');
$xmlTool = new FR3D\XmlDSig\Adapter\XmlseclibsAdapter();
$xmlTool->setPrivateKey(file_get_contents('C:\xampp\htdocs\EgovPayments\private1.pem'));
$publicKey=$xmlTool->getPublicKey();
//echo 'public key is:'.$publicKey;
$xmlTool->setPublicKey($publicKey);
$xmlTool->addTransform(FR3D\XmlDSig\Adapter\AdapterInterface::ENVELOPED);
$xmlTool->setCanonicalMethod('http://www.w3.org/2001/10/xml-exc-c14n#');
$xmlTool->sign($data);
$data->saveXML();
But nothing changed in newdata.xml, how it work with xmldsig in PHP?
thx
The function DOMDocument::saveXML() returns string. It is not to update file.
http://php.net/manual/en/domdocument.savexml.php
i've got the same problem - but find the following function "insertSignature" in the seclib.
if you use the Adapter add the following line to the end of the verify-function:
$objXMLSecDSig->insertSignature($data->getElementsByTagName("Security")->item(0));
I have the following XML document:
<?xml version="1.0"?>
<GetMatchingProductForIdResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
<GetMatchingProductForIdResult Id="B0009VCOU4" IdType="ASIN" status="Success">
<Products xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01" xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd">
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>ATVPDKIKX0DER</MarketplaceId>
<ASIN>B0009VCOU4</ASIN>
</MarketplaceASIN>
</Identifiers>
<AttributeSets>
<ns2:ItemAttributes xml:lang="en-US">
<ns2:Binding>Electronics</ns2:Binding>
<ns2:Brand>DOBANI</ns2:Brand>
<ns2:Feature>Handcrafted Quality, Value Priced</ns2:Feature>
<ns2:Feature>Satisfaction Guaranteed! 30-Day Return Policy!</ns2:Feature>
<ns2:ItemDimensions>
<ns2:Height Units="inches">7.00</ns2:Height>
<ns2:Length Units="inches">6.00</ns2:Length>
<ns2:Width Units="inches">6.00</ns2:Width>
</ns2:ItemDimensions>
<ns2:Label>Mid-East</ns2:Label>
<ns2:ListPrice>
<ns2:Amount>9.90</ns2:Amount>
<ns2:CurrencyCode>USD</ns2:CurrencyCode>
</ns2:ListPrice>
<ns2:Manufacturer>Mid-East</ns2:Manufacturer>
<ns2:Model>BULB</ns2:Model>
<ns2:PackageDimensions>
<ns2:Height Units="inches">3.70</ns2:Height>
<ns2:Length Units="inches">8.10</ns2:Length>
<ns2:Width Units="inches">4.00</ns2:Width>
<ns2:Weight Units="pounds">0.35</ns2:Weight>
</ns2:PackageDimensions>
<ns2:PackageQuantity>1</ns2:PackageQuantity>
<ns2:PartNumber>BULB</ns2:PartNumber>
<ns2:ProductGroup>Single Detail Page Misc</ns2:ProductGroup>
<ns2:ProductTypeName>MUSICAL_INSTRUMENTS</ns2:ProductTypeName>
<ns2:Publisher>Mid-East</ns2:Publisher>
<ns2:SmallImage>
<ns2:URL>http://ecx.images-amazon.com/images/I/31Fsu5jKWsL._SL75_.jpg</ns2:URL>
<ns2:Height Units="pixels">75</ns2:Height>
<ns2:Width Units="pixels">50</ns2:Width>
</ns2:SmallImage>
<ns2:Studio>Mid-East</ns2:Studio>
<ns2:Title>Spare Rubber Bulb</ns2:Title>
</ns2:ItemAttributes>
</AttributeSets>
<Relationships/>
<SalesRankings>
<SalesRank>
<ProductCategoryId>sdp_misc_display_on_website</ProductCategoryId>
<Rank>36468</Rank>
</SalesRank>
</SalesRankings>
</Product>
</Products>
</GetMatchingProductForIdResult>
<ResponseMetadata>
<RequestId>afnapq823haeufabq2rhalhtz</RequestId>
</ResponseMetadata>
</GetMatchingProductForIdResponse>
I am trying to get the package dimensions, but none of my xpath queries work. Have tried these using PHP's built-in xpath functions and using QueryPath 3.0.0, but neither works.
This doesn't work even though XML Tree in Chrome shows it should:
/GetMatchingProductForIdResponse/GetMatchingProductForIdResult/Products/Product/AttributeSets/ns2:ItemAttributes/ns2:PackageDimensions/ns2:Height
I thought neutralizing the namespace would get rid of the problem since the above triggers a namespace error, but it does not:
/GetMatchingProductForIdResponse/GetMatchingProductForIdResult/Products/Product/AttributeSets/*[local-name()='ItemAttributes']/*[local-name()='PackageDimensions']/*[local-name()='Height']
Xpath has no default namespace. The Xpath provided by Chrome is invalid. An Xpath element expression without a namespace prefix always matches elements without a namespace.
You need to register your own namespace prefixes and use them:
$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);
$xpath->registerNamespace(
'p', 'http://mws.amazonservices.com/schema/Products/2011-10-01'
);
$xpath->registerNamespace(
'pd', 'http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd'
);
$result = $xpath->evaluate(
'string(
/p:GetMatchingProductForIdResponse
/p:GetMatchingProductForIdResult
/p:Products
/p:Product
/p:AttributeSets
/pd:ItemAttributes
/pd:PackageDimensions
/pd:Height
)'
);
var_dump($result);
Output: https://eval.in/150409
string(4) "3.70"
I'm afraid even the first part of your xpath is suffering for the namespace issue. Have you tried :
/*[local-name()='GetMatchingProductForIdResponse']/*[local-name()='GetMatchingProductForIdResult']/*[local-name()='Products']/*[local-name()='Product']/*[local-name()='AttributeSets']/*[local-name()='ItemAttributes']/*[local-name()='PackageDimensions']/*[local-name()='Height']
I think to use the normal xpath approach, you will need to set the corresponding namespaces on the xpath evaluator itsself.
/**
* Convert XML to JSON and return.
*/
$response = preg_replace("/(<\/?)(\w+):([^>]*>)/", "$1$2$3", $response);
$xml = simplexml_load_string($response);
$json = json_encode($xml);
return json_decode($json,TRUE);
This worked for me
We have a PHP application which needs to connect to this SOAP web service—here's the WSDL: https://arixss.arifleet.com/QA/DriveAwayWS/DriveAwaySrvc.svc?wsdl
The vendor claims it uses "WS-Security (wsHttpBinding)". This doesn't mean much to me, as I don't have experience beyond "normal" unauthenticated SOAP. Furthermore, I understand there are probably several ways to implement WS-Security, and the vendor hasn't provided a full specification.
So far, thanks to the WSSoap class given in this answer, I have been able to connect, authenticate, and run the GetAllRequests method successfully. However, I'm stuck when trying to run the GetRequestDetail method, because I don't know what kind of parameter argument to use. The vendor offers this snippet of .NET code as an example:
DriveAwayClient client = new DriveAwayClient();
client.ClientCredentials.UserName.UserName = "…";
client.ClientCredentials.UserName.Password = "…";
ARIRqst rqst = new ARIRqst();
rqst.RqstType = "ORDER";
rqst.OrderID = "12345";
string RequestDetail;
RequestDetail = client.GetRequestDetail(rqst);
This code can't be rewritten in PHP (at least using the WSSoap class) because I have no way of injecting a ARIRqst object using WSSoap. Furthermore, I wouldn't know how to instantiate a ARIRqst object, because I don't have access to a ARIRqst() class in PHP.
I thought if I knew more about the specific requirements of this web service, as defined by the WSDL—what its specific type is, and what authentication is used—I would have better luck finding an example in PHP which can consume it, or at least find the specifications so that I could write my own implementation.
UPDATE: To be specific, I ultimately just need to know how to format the request for this web service's GetRequestDetail method. Here's what I'm sending:
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="http://tempuri.org/">
<s:Header>
<a:Action s:mustUnderstand="1">http://tempuri.org/IDriveAway/GetRequestDetail</a:Action>
<a:MessageID>urn:uuid:eacedde2-cec5-4da1-afbf-822fe2e92793</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">https://arixss.arifleet.com/QA/DriveAwayWS/DriveAwaySrvc.svc?wsdl</a:To>
<o:Security xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" s:mustUnderstand="1">
<u:Timestamp u:Id="_0">
<u:Created>2014-04-08T23:20:00Z</u:Created>
<u:Expires>2014-04-08T23:25:00Z</u:Expires>
</u:Timestamp>
<c:SecurityContextToken xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc" u:Id="uuid-85c09ef0-83e1-417c-b9c7-5892798ee739-197">
<c:Identifier>urn:uuid:24d56285-84f1-4c74-8093-5f72090ab92f</c:Identifier>
</c:SecurityContextToken>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1"/>
<Reference URI="#_0">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>[REDACTED]</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>[REDACTED]</SignatureValue>
<KeyInfo>
<o:SecurityTokenReference>
<o:Reference ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct" URI="#uuid-85c09ef0-83e1-417c-b9c7-5892798ee739-197"/>
</o:SecurityTokenReference>
</KeyInfo>
</Signature>
</o:Security>
</s:Header>
<s:Body>
<ns1:GetRequestDetail xsi:type="ns1:ARIRqst">
<RqstType>ORDER</RqstType>
<RqstID>1234</RqstID>
<OrderID>1234-1</OrderID>
<QuoteID>1</QuoteID>
</ns1:GetRequestDetail>
</s:Body>
</s:Envelope>
And here is the response from the server, containing an InternalServiceFault of "Object reference not set to an instance of an object" (which I assume means I'm not encoding the ARIRqst object correctly in the request):
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1">http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher/fault</a:Action>
<a:RelatesTo>urn:uuid:c0af2ed0-9afb-4c77-a09f-2463bf5cbc52</a:RelatesTo>
<o:Security xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" s:mustUnderstand="1">
<u:Timestamp u:Id="_0">
<u:Created>2014-04-08T23:20:26.872Z</u:Created>
<u:Expires>2014-04-08T23:25:26.872Z</u:Expires>
</u:Timestamp>
</o:Security>
</s:Header>
<s:Body>
<s:Fault>
<s:Code>
<s:Value>s:Receiver</s:Value>
<s:Subcode>
<s:Value xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:InternalServiceFault</s:Value>
</s:Subcode>
</s:Code>
<s:Reason>
<s:Text xml:lang="en-US">Object reference not set to an instance of an object.</s:Text>
</s:Reason>
<s:Detail>
<ExceptionDetail xmlns="http://schemas.datacontract.org/2004/07/System.ServiceModel" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<HelpLink i:nil="true"/>
<InnerException i:nil="true"/>
<Message>Object reference not set to an instance of an object.</Message>
<StackTrace> at ARI.DriveAwayMgr.DriveAwaySrvc.GetRequestDetail(ARIRqst rqst) in d:\[REDACTED]\DriveAwaySrvc.svc.cs:line 189
at SyncInvokeGetRequestDetail(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)</StackTrace>
<Type>System.NullReferenceException</Type>
</ExceptionDetail>
</s:Detail>
</s:Fault>
</s:Body>
</s:Envelope>
<?php
$client = new SoapClient('http://soap.amazon.com/schemas3/AmazonWebServices.wsdl');
var_dump($client->__getFunctions());
?>
From php.net.
Just insert the wsdl into the SoapClient call...it should return all methods and parameters...
You can wrap it in a try catch block also
I am trying to parse xml file from amazon but found difficulties. I am using simplexml_load_string
$xml = simplexml_load_string( 'My xml here' );
but when I do
echo $xml->GetMatchingProductResult->Product->AttributeSets;
it shows nothing
How can I access the Brand value?
My xml file:
<?xml version="1.0"?>
<GetMatchingProductResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
<GetMatchingProductResult ASIN="B003IOSNNQ" status="Success">
<Product xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01" xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd">
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>A1F83G8C2ARO7P</MarketplaceId>
<ASIN>B003IOSNNQ</ASIN>
</MarketplaceASIN>
</Identifiers>
<AttributeSets>
<ns2:ItemAttributes xml:lang="en-GB">
<ns2:Binding>Misc.</ns2:Binding>
<ns2:Brand>eSecure</ns2:Brand>
<ns2:Feature>Colour: Classic Black</ns2:Feature>
<ns2:Feature>Thickness: Approximately 40mm - More than msot sellers</ns2:Feature>
<ns2:Feature>Dimensions [length x width at widest and narrowest]: approximately 280 x 190 x 70mm</ns2:Feature>
<ns2:Feature>Material: Stretch Lycra, Silica Gel</ns2:Feature>
<ns2:Feature>Ideal for Standard Bicycle / Static Exercise Bike</ns2:Feature>
<ns2:Label>eSecure</ns2:Label>
<ns2:Manufacturer>eSecure</ns2:Manufacturer>
<ns2:PackageDimensions>
<ns2:Height Units="inches">2.13</ns2:Height>
<ns2:Length Units="inches">10.71</ns2:Length>
<ns2:Width Units="inches">7.72</ns2:Width>
<ns2:Weight Units="pounds">0.49</ns2:Weight>
</ns2:PackageDimensions>
<ns2:PackageQuantity>1</ns2:PackageQuantity>
<ns2:ProductGroup>Sports</ns2:ProductGroup>
<ns2:ProductTypeName>SPORTING_GOODS</ns2:ProductTypeName>
<ns2:Publisher>eSecure</ns2:Publisher>
<ns2:SmallImage>
<ns2:URL>http://ecx.images-amazon.com/images/I/41OIjmpza2L._SL75_.jpg</ns2:URL>
<ns2:Height Units="pixels">75</ns2:Height>
<ns2:Width Units="pixels">75</ns2:Width>
</ns2:SmallImage>
<ns2:Studio>eSecure</ns2:Studio>
<ns2:Title>eSecure - Extra Comfort Bike Bicycle Gel Saddle Seat Cover</ns2:Title>
</ns2:ItemAttributes>
</AttributeSets>
<Relationships/>
<SalesRankings>
<SalesRank>
<ProductCategoryId>sports_display_on_website</ProductCategoryId>
<Rank>398</Rank>
</SalesRank>
<SalesRank>
<ProductCategoryId>458338031</ProductCategoryId>
<Rank>1</Rank>
</SalesRank>
</SalesRankings>
</Product>
</GetMatchingProductResult>
<ResponseMetadata>
<RequestId>9b44aba6-d1fa-486a-8114-2bc4f9311d8d</RequestId>
</ResponseMetadata>
</GetMatchingProductResponse>
I know this is an old question but I had a hard time with the same thing.
First simplexml_load_string doesn't handle the namespaces thrown in like this, so you could go recursively and check and then load the namespaces, evaluate the xml and waste a lot of time ...
In my case I didn't care about evaluating the format of the xml with the namespaces, so I just removed them from the string with regex. After this simplexml_load_string won't omit those parts anymore and it's easy to get an array out of it with json_encode and json_decode.
//convert an xml string into an array
function xml2array($xml){
$xml = preg_replace('/(<\/?)\w+:([^>]*>)/', '$1$2', $xml); //get rid of namespaces
$xml = simplexml_load_string($xml);
return json_decode(json_encode($xml),true); //use built-in stuff
}
The only problem with this is when the xml is full of attributes containing useful data, then you would need something else instead of simplexml_load_string. Note that it returns an #attributes element from this:
<GetMatchingProductResult ASIN="B003IOSNNQ" status="Success">
but omits it from this part:
<Width Units="pixels">75</Width>
I have no idea why or how deep down it would check in the nested tags.
echo $xmlobj->children('',true)->ListMatchingProductsResult->Products->Product->AttributeSets->children('ns2',true)->ItemAttributes->Brand.PHP_EOL;